Technical Deep Dive: Architecture Choices for Subscriptions on the Blockchain (ERC948)
Architecture choices for ERC948 — Subscriptions on Ethereum
Subscriptions are one of the healthiest monetization methods on the legacy web. At Gitcoin, we believe this will prove to be so on Web 3.0, as well.
Unlike surveillance capital based models, subscriptions still fit within the Web 3 ethos, which prioritizes the following ideals.
- Data to users: Information is owned by the users, and provided to corporations, businesses, or services who hope to benefit the user
- Censorship resistance: No government, company, or institution should control your access to information (1, 2, 3)
- Transparent, open networks: “First, the contract between cryptonetworks and their participants is enforced in open source code. Second, they are kept in check through mechanisms for ‘voice’ and ‘exit.’” — Chris Dixon, (4)
- Push, not pull: ‘Push’ your information to trusted sources, instead of ‘pulling’ from other sources who ultimately own the data (5)
To this point, token based models have been the focus in Web 3 (for good reason). However, subscriptions are preferable to token based systems for both users and founders in some cases.
- Users don’t have to read a complex whitepapers to assess dApp token utility / token vesting schedules
- Users can cancel anytime, without having to own any tokens
- Founders can get a consistent, ongoing stream of cash flow while assessing the health of their business (subscribers, churn, growth)
- Founders can focus on making customers happy, as opposed to splitting time between speculators and users
For these reasons, we think it’s worth creating a standard way to do subscriptions on Ethereum.
Learn more about the groundbreaking token protocol proposal designed to connect subscription businesses with consumersmedia.consensys.net
Our progress thus far
The remainder of this article is meant to be a pros and cons exercise for the different architectures of subscription transactions proposed in the ERC948 working group. We examine the execution of subscription transactions and will allow the 948 spec to follow the chosen execution architecture. All of these thoughts are in progress. Nothing is final. We probably make drastic generalizations, silly assumptions, and bias possibilities toward the projects we are building. We welcome comments and feedback.
UX design considerations
Here are some attributes of the web 2.0 subscription user experience we think would be healthy to carry over to web 3.0 subscriptions.
- Safety first. If the architecture is not able to keep user funds secure, it is a non-starter.
- No Staking. A user should not have to stake funds. i.e. lock 1.2 ETH for a subscription that pays out 0.1 ETH per month.
- Minimize UX Complexity. A user should not have to create a new wallet to manage their subscriptions. Key management is hard enough already, we don’t need another set of keys to keep track of.
- Opt-Out First. A user should not need to perform actions on an on-going basis. It should be a “set it and forget it” experience. A subscriber performs one transaction to set the subscription in motion and transactions should happen “automatically” between the parties.
- Minimizes Gas Use: The standard should be as efficient of a consumer of on-chain resources as possible
- Bonus: Extensibility. It’d be great if the standard could be extended to any recurring action (not just ERC20/ETH transfers)
Option 1: User Driven Transactions
User Driven Transaction are “traditional” transactions in Ethereum. These transactions are entirely on-chain and conducted fully by the participants of the transaction.
Below is a simplified diagram of the transaction flow followed by a step-through on the process.
- A _subscriber calls both a ‘createSubscription( )’ function which designates the _provider and payment interval of the subscription, and an ‘approve( )’ which allows the subscription contract to ‘transferFrom( )’ an ERC20 contract. The ‘approve( )’ call needs to only be done once for each ERC20 and subscription contract.
- The _provider stores events emitted on subscription creation and with each successive withdrawal, and calls the ‘executeSubscription( )’ function at the specified intervals.
- Battle tested design, nothing new.
- Simple system.
- Easily implemented with current wallets.
- Focuses only on ERC20 transfers.
Option 2: Limited Delegation Transactions
Limited Delegated Transactions are conducted mostly on-chain and allow a _processor, but require Processors be explicitly approved. Processors are a third party that has been approved to process the transaction on behalf of the _provider.
- A _subscriber calls both a ‘createSubscription( )’ function which designates the _provider, _processor, and payment interval of the subscription, and an ‘approve( )’ which allows the subscription contract to ‘transferFrom( )’ an ERC20 contract. The ‘approve( )’ call needs to only be done once for each ERC20 and subscription contract. The _processor can be a single entity, a multiSig, or an array of approved addresses. Delegations are limited though in that processors must be explicitly approved.
- The _processor stores events relevant to them on subscription creation and on each successive withdrawal, and calls the ‘executeSubscription( )’ function at the specified intervals.
- Design is easily implemented using current wallets.
- Simpler design than Meta Transactions.
- Requires assessment of pattern and battle testing in the wild.
- Heavy on chain data use may be expensive and lead to chain bloat.
- Delegations are limited and not super flexible.
- Relies on Processor to keep track of subscription intervals.
- Focuses on ERC20 transfer.
Option 3: Meta Transactions
Meta Transactions are an emerging pattern in the Ethereum ecosystem and look to provide a number of benefits.
Meta transactions consist of a signed message of intent from the user that can be delegated to any processor and which can be used at recurring intervals.
- A _subscriber calls a ‘createSubscription( )’ function which stores a minimal data set on chain, an ‘approve( )’ which allows the subscription contract to ‘transferFrom( )’ an ERC20 contract, and has the _subscriber sign a message that indicates the intent of their subscription. This signed message is then passed on to the _provider. The ‘approve( )’ call needs to only be done once for each ERC20 and subscription contract, and may not be necessary if the user is conducting an action unrelated to an ERC20 token.
- The _provider stores the signed message and at the specified interval can either call ‘executeSubscription( )’ or pass on the signed message to a _processor or processor network which will call the function on the _provider’s behalf.
- Allows for any type of recurring action. ETH Transfer, ERC20 transfer, Call, DelegateCall, any arbitrary action on chain.
- Allows for N processors without explicit approval.
- Might prove useful for other enhancements in UX.
- Cheaper gas costs per transaction.
- Requires assessment of pattern and battle testing in the wild.
- Requires a new wallet implementation.
- Much more complicated design.
Here is a summary of each of the methods (rows), and the considerations (columns).
As demonstrated above there are a number of ways to accomplish recurring transactions on the Ethereum blockchain. I will refrain from prescribing any solution and allow the conversation to continue in the community. My hope is that this article sheds light on how these systems might work and toward the best direction for ERC948.
Special thanks to Andrew Redden of Groundhog for walking me through his thoughts on Meta Transactions and how they might work with subscriptions. Many of his ideas are found in the Meta Transaction section. Also thanks to Austin Griffith for his Bouncer Proxy demo which made the idea of Meta Transactions much easier to grasp. A final thanks to the whole 948 working group — we stand on the shoulders of giants.
To learn more about Gitcoin, click below.