-
Notifications
You must be signed in to change notification settings - Fork 15
Chronologic / Piper standard #16
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
# Specification | ||
|
||
## Summary | ||
A standardized interface for interacting with subscriptions. | ||
|
||
## Abstract | ||
This standard defines a contract interface for interacting with subscription data. The scope of this proposal is end-user / wallet interactions. Creation of the subscriptions is out-of-scope of this ERC. | ||
|
||
## Our Thoughts | ||
From the subscriber's side: | ||
|
||
* I want strong guarantees on when I can cancel my subscription. | ||
* I will normally want payments to happen automatically without any action on my part. | ||
* In some cases it might be valuable to require an approval process. | ||
* For dynamically priced subscriptions I want to be able to set limits (require authorization if subscription is more than X). | ||
|
||
|
||
From the providers's side: | ||
|
||
* I need the ability to charge a fixed fee per subscription time unit (netflix, pandora, etc). | ||
* I need the ability to charge a dynamic fee per subscription time unit (aws, twilio, etc). | ||
* I need to be able to create reasonably accurate forecasts for upcoming subscriptions: Programatic checks that subscription accounts have available balance and that subscription is active. | ||
|
||
## Motivation | ||
Standard that covers all usecases of subscription based model with minimal interface suitable for wallets. | ||
|
||
### Interface | ||
|
||
#### cancel | ||
|
||
Immediately cancels the subscription. Implementations should ensure that any unpaid subscription payments are paid to the provider as part of cancellation to ensure providers are able to let subscriptions fees fill up for arbitrary lengths of time, allowing them to reduce overhead from transaction costs. | ||
|
||
```SOLIDITY | ||
|
||
/** @dev Cancels the subscription | ||
* @return true if cancellation succedded | ||
*/ | ||
|
||
function cancel() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Standard interface should not be limited to a "contract-per-subscription" model. I believe UUID should be provided at the least. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is more of the architectural choice to keep contract-per-subscription model. Given that subscription is going to hold the value, regardless whether ETH or tokens, we are striving to eliminate the honeypot problem. |
||
public | ||
returns (bool success); | ||
``` | ||
|
||
#### isFunded | ||
|
||
Checkes if there is enough funds available for the provider to collect | ||
|
||
```SOLIDITY | ||
|
||
/** @dev Cancels the subscription | ||
* @return true if there is enough funds allowed to the contract to pay for subscription | ||
*/ | ||
|
||
function isFunded() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As we've discussed on Friday - this might be helpful wrapper but needs further discussion if it's really needed. Alternative is:
Thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even in the case of ETH, you probably want to store it in ERC20 compatible "vault" which makes this work by default. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will remove the burden of implementing this functionality outside the smart contract and provides the precise way to see the status of the subscription. |
||
public | ||
returns (bool funded); | ||
``` | ||
|
||
#### availableFunds | ||
|
||
Returns the amount of ETH or tokens available for the provider to collect | ||
|
||
|
||
```SOLIDITY | ||
|
||
/** @dev The amount of ETH or tokens available for the provider | ||
* @return available funds | ||
*/ | ||
|
||
function availableFunds() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Above discussion applies to this function, too. |
||
public | ||
returns (uint256 funds); | ||
``` | ||
|
||
#### metadataURI | ||
|
||
Returns URI (RFC 3986) for subscription metadata | ||
By *metadata* we define a self-described data not required by on-chain contract logic and thus possible to be kept off-chain. An example provided [here](#metadata-example) | ||
|
||
```SOLIDITY | ||
|
||
/** @dev URI string to subscription metadata | ||
* @return URI to metadata | ||
*/ | ||
|
||
function metadataURI() | ||
public | ||
returns (string metadataURI); | ||
``` | ||
|
||
|
||
|
||
### Implementation | ||
|
||
A minimal implementation would require the following fields. | ||
|
||
* `address token`: defines the token contract which payments are paid from. | ||
* `address provider`: the address of the provider | ||
* `uint256 time_unit`: the number of seconds per time unit. | ||
* `uint256 tokens_per_time_unit`: the number of tokens that can be paid towards the subscription per time_unit. | ||
* `uint256 last_payment_at`: the timestamp when the last payment was made. | ||
|
||
In order to allow triggering payments by external parties the contract can follow EIP #1228. | ||
|
||
The `execute` method would call `token.transfer(provider, (now - last_payment_at) * tokens_per_time_unit / time_unit)`. | ||
|
||
### Metadata example | ||
|
||
Basic information about the subscription: | ||
* name = "Monthly subscription" | ||
* description = "Any other extra description to be visible from wallet" | ||
* key = "value" | ||
|
||
Which can be JSON serialized as | ||
|
||
```Json | ||
{"name":"Monthly subscription","description":"Any other extra description to be visible from wallet","key":"value"} | ||
``` | ||
|
||
Things to consider: | ||
* limit the amount of keys and values | ||
|
||
### Conclusion | ||
This is our suggestions for the beginning of a standardization on interaction with subscription data on the Ethereum blockchain. We are open to suggestions, concerns, or rejections. Let's collaborate and build a better ecosystem. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we can ensure any payment executions since there are many different scenarios when the payment execution is not possible (eg. subscriber has insufficient funds).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can ensure unclaimed funds are paid if there are sufficient funds though. If there are not sufficient funds, perhaps there is a debt pattern that we can employ here. It may be out of scope for the standard but could be outlined as a suggested option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest leaving this for the provider / processor to handle. For instance, they could postpone a payment N-times until finally cancelling the subscription.
Subscriptions in fiat for example also cannot ensure the actual payment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree that's a little bit tricky. I was thinking to combine this with
isFunded
and/oravailableFunds
function described above.So the scenario from the provider perspective is: