Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EIP 1337 -- Subscriptions on the blockchain. #1337

Closed
wants to merge 10 commits into from
262 changes: 262 additions & 0 deletions EIPS/eip-1337.md
@@ -0,0 +1,262 @@
---
eip: 1337
title: [WIP] Subscriptions on the blockchain.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of [WIP] the field Status: Draft should be added.

Suggested change
title: [WIP] Subscriptions on the blockchain.
title: Subscriptions on the blockchain.
status: Draft

author:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please format this in a single line, comma-separated, with either username or email address (not both)

* Kevin Owocki <kevin@gitcoin.co> (@owocki)
* Andrew Redden <andrew@blockcrushr.com> (@androolloyd)
* Scott Burke <scott@blockcrushr.com> (@sb777)
* Kevin Seagraves <k.s.seagraves@gmail.com> (@captnseagraves)
* Luka Kacil <luka.kacil@gmail.com>
* Štefan Šimec <stefan.simec@gmail.com>
* Piotr Kosiński (@kosecki123)
* ankit raj <tradeninja7@gmail.com> (@aj07)
* John Griffin <john@atchai.com> (@johngriffin)
* Nathan Creswell <nathantr@gmail.com> (@nathcres)

discussions-to:[this github issue url](https://github.com/EthereumOpenSubscriptions/standard/issues) or [Gitcoin Slack](https://gitcoin.co/slack) in #proj-subscriptions channel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please format this as just a URL.

type: Interface
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Interface" is not a type; perhaps this should be "Standards Track"?

category Interface
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a colon here.

created: 2018-08-01
requires (*optional): ERC-20, ERC-948, EIP-165
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove (*optional)

replaces (*optional):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this.

---

<!--You can leave these HTML comments in your merged EIP and delete the visible duplicate text guides, they will not appear and may be helpful to refer to if you edit it again. This is the suggested template for new EIPs. Note that an EIP number will be assigned by an editor. When opening a pull request to submit your EIP, please use an abbreviated title in the filename, `eip-draft_title_abbrev.md`. The title should be 44 characters or less.-->

## Simple Summary
<!--"If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the EIP.-->
Monthly subscriptions are a key monetization channel for legacy web, and arguably they are the most healthy monetization channel for businesses on the legacy web (especially when compared to ad/surveillance) based models. They are arguably more healthy than a token based economic system (depending upon the vesting model of the ICO) because
#####For a user:
* you don't have to read a complex whitepaper to use a dapps utility (as opposed to utility tokens)
* you don't have to understand the founder's vesting schedules
* you can cancel anytime

#####For a Service Provider:
* since you know your subscriber numbers, churn numbers, conversion rate, you get consistent cash flow, and accurate projections
* you get to focus on making your customers happy
* enables you to remove speculators from your ecosystem

For these reasons, we think it's imperative to create a standard way to do 'subscriptions' on Ethereum.

## Abstract
<!--A short (~200 word) description of the technical issue being addressed.-->
To enable replay-able transactions users sign a concatenated bytes hash that is composed of the input data needed to execute the transaction. This data is stored off chain by the recipient of the payment and is transmitted to the customers smart contract for execution alongside a provided signature.

## Motivation
<!--The motivation is critical for EIPs that want to change the Ethereum protocol. It should clearly explain why the existing protocol specification is inadequate to address the problem that the EIP solves. EIP submissions without sufficient motivation may be rejected outright.-->
Recurring payments are the bedrock of SaSS and countless other businesses, a robust specification for defining this interaction will enable a broad spectrum of revenue generation and business models.

## Specification
<!--The technical specification should describe the syntax and semantics of any new feature. The specification should be detailed enough to allow competing, interoperable implementations for any of the current Ethereum platforms (go-ethereum, parity, cpp-ethereum, ethereumj, ethereumjs, and [others](https://github.com/ethereum/wiki/wiki/Clients)).-->
#### Enum Contract

EIP-1337 Contracts should be compiled with a contract that references all the enumerations that are required for operation

```SOLIDITY
/// @title Enum - Collection of enums
/// Original concept from Richard Meissner - <richard@gnosis.pm> Gnosis safe contracts
contract Enum {
enum Operation {
Call,
DelegateCall,
Create,
ERC20,
ERC20Approve
}
enum SubscriptionStatus {
ACTIVE,
PAUSED,
CANCELLED,
EXPIRED
}
}
```



#### EIP-165

ERC-948 Compliant contracts support EIP-165 announcing what interfaces they support

```SOLIDITY
interface ERC165 {
/**
* @notice Query if a contract implements an interface
* @param interfaceID The interface identifier, as specified in ERC-165
* @dev Interface identification is specified in ERC-165. This function
* uses less than 30,000 gas.
* @return `true` if the contract implements `interfaceID` and
* `interfaceID` is not 0xffffffff, `false` otherwise
**/
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
```



#### Public View Functions

###### isValidSubscription
```SOLIDITY

/** @dev Checks if the subscription is valid.
* @param bytes subscriptionHash is the identifier of the customer's subscription with its relevant details.
* @return success is the result of whether the subscription is valid or not.
**/

function isValidSubscription(
uint256 subscriptionHash
)
public
view
returns (
bool success
)
```
###### getSubscriptionStatus
```SOLIDITY

/** @dev returns the value of the subscription
* @param bytes subscriptionHash is the identifier of the customer's subscription with its relevant details.
* @return status is the enumerated status of the current subscription, 0 expired, 1 active, 2 paused, 3 cancelled
**/
function getSubscriptionStatus(
uint256 subscriptionHash
)
public
view
returns (
Enum.SubscriptionStatus status,
uint256 nextWithdraw,
bytes32 externalId
)
```

###### getSubscriptionHash

```SOLIDITY
/** @dev returns the hash of cocatenated inputs to the address of the contract holding the logic.,
* the owner would sign this hash and then provide it to the party for execution at a later date,
* this could be viewed like a cheque, with the exception that unless you specifically
* capture the hash on chain a valid signature will be executable at a later date, capturing the hash lets you modify the status to cancel or expire it.
* @param address recipient the address of the person who is getting the funds.
* @param uint256 value the value of the transaction
* @param bytes data the data the user is agreeing to
* @param uint256 txGas the cost of executing one of these transactions in gas(probably safe to pad this)
* @param uint256 dataGas the cost of executing the data portion of the trasnaction(delegate calls etc)
* @param uint 256 gasPrice the agreed upon gas cost of Execution of this subscription(cost incurment is up to implementation, ie, sender or reciever)
* @param address gasToken address of the token in which gas will be compensated by, address(0) is ETH, only works in the case of an enscrow implementation)
* @return bytes32, return the hash input arguments concatenated to the address of the contract that holds the logic.
**/
function getSubscriptionHash(
address recipient,
uint256 value,
bytes data,
Enum.Operation operation,
uint256 txGas,
uint256 dataGas,
uint256 gasPrice,
address gasToken
)
public
view
returns (
bytes32 subscriptionHash
)
```


###### getModifyStatusHash

```SOLIDITY
/** @dev returns the hash of concatenated inputs that the owners user would sign with their public keys
* @param address recipient the address of the person who is getting the funds.
* @param uint256 value the value of the transaction
* @return bytes32 returns the hash of concatenated inputs with the address of the contract holding the subscription hash
**/
function getModifyStatusHash(
bytes32 subscriptionHash
Enum.SubscriptionStatus status
)
public
view
returns (
bytes32 modifyStatusHash
)
```
#### Public Functions


###### modifyStatus
```SOLIDITY

/** @dev modifys the current subscription status
* @param uint256 subscriptionHash is the identifier of the customer's subscription with its relevant details.
* @param Enum.SubscriptionStatus status the new status of the subscription
* @param bytes signatures of the requested method being called
* @return success is the result of the subscription being paused
**/
function modifyStatus(
uint256 subscriptionHash,
Enum.SubscriptionStatus status,
bytes signatures
)
public
returns (
bool success
)
```

###### executeSubscription
```SOLIDITY

/** @dev returns the hash of cocatenated inputs to the address of the contract holding the logic.,
* the owner would sign this hash and then provide it to the party for execution at a later date,
* this could be viewed like a cheque, with the exception that unless you specifically
* capture the hash on chain a valid signature will be executable at a later date, capturing the hash lets you modify the status to cancel or expire it.
* @param address recipient the address of the person who is getting the funds.
* @param uint256 value the value of the transaction
* @param bytes data the data the user is agreeing to
* @param uint256 txGas the cost of executing one of these transactions in gas(probably safe to pad this)
* @param uint256 dataGas the cost of executing the data portion of the trasnaction(delegate calls etc)
* @param uint 256 gasPrice the agreed upon gas cost of Execution of this subscription(cost incurment is up to implementation, ie, sender or reciever)
* @param address gasToken address of the token in which gas will be compensated by, address(0) is ETH, only works in the case of an enscrow implementation)
* @param bytes signatures signatures concatenated that have signed the inputs as proof of valid execution
* @return bool success something to note that a failed execution will still pay the issuer of the transaction for their gas costs.
**/
function executeSubscription(
address to,
uint256 value,
bytes data,
Enum.Operation operation,
uint256 txGas,
uint256 dataGas,
uint256 gasPrice,
address gasToken,
bytes signatures
)
public
returns (
bool success
)
```

## Rationale
<!--The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion.-->
Merchants who accept credit-cards do so by storing a token that is retrieved from a third party processor(stripe, paypal, etc), this token is used to grant access to pull payment from the cx's credit card provider and move funds to the merchant account.
Having users sign input data acts in a similliar fashion and enables that merchant to store the signature of the concatenated bytes hash and input data used to generate the hash and pass them off to the contract holding the subscription logic, thus enabling a workflow that is similliar to what exists in the present day legacy web.

## Backwards Compatibility
<!--All EIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The EIP must explain how the author proposes to deal with these incompatibilities. EIP submissions without a sufficient backwards compatibility treatise may be rejected outright.-->
N/A

## Test Cases
<!--Test cases for an implementation are mandatory for EIPs that are affecting consensus changes. Other EIPs can choose to include links to test cases if applicable.-->
[WIP]

## Implementation
<!--The implementations must be completed before any EIP is given status "Final", but it need not be completed before the EIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details.-->
[WIP]

## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).