-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
Recurring Subscription Models are a Good Thing and should be viable on Ethereum (Merit + Architecture ERC) #948
Comments
I like this. SAAS subscriptions aren't usually just a binary thing where they're just either active or not -- you might pick a service level or price point or number of users or whatever options to configure the sub & maybe that's done in the service's traditional web application. But it seems like if you're basically signing a contract, the various terms beyond whether the sub is active/inactive as well as pricing details etc should be somehow linked to this abstraction for the purpose of recording what the user signs for. So, to break it down, it seems to me like you could have terms parameters(which could be adjusted potentially with implications on payment), payment calculation, and a signature working together on this. Although for an MVP, would probably be good to just focus on as though the terms are just binary -- user is subscribed, user is unsubscribed. |
Do you feel you'd want to make sure the user signed a transaction associated with the subscription every time a payment was due? This is basically like a double opt-in, which is better for the consumer. If they don't approve/sign the transaction requesting, the service or product does not go to them. Out-out by default? |
Maybe this was already in the plan but yeah it'd be nice ux to have a subscription registry service for all your subscriptions (with updates aggregated in 1 sweep / notification / single monthly or annual transaction by the user then auto-paid to each service). Might be more of a dapp tho like http://scroogeup.com or a budgeting app or advanced wallet but maybe it could be an ERC. |
For the case of tokens, couldn't you do something similar to 0x, where you give an unlimited allowance to a smart contract which has clearly bounded functionality (to only allow withdrawals of amounts you approve, on a certain interval)?
This would allow the user to authorize an ongoing subscription with one-time setup, and no need to escrow funds. Would this satisfy your requirements? Doing this with ETH is probably harder, as there's nothing like the "approve" function that I'm aware of. |
Recurring payments are very important. One unaddressed issue in this model is volatility. For users to grant price-based withdrawals to a contract, the oracle needs to be able to disable withdrawals during periods of high volatility. |
Love this idea. An important discussion to have is whether this should be baked into Ethereum or whether this should be it's own project built on top of Ethereum. Personally I believe it's so critical to the development of the dapp ecosystem that a core standard or new functionality that enables this sort of subscription with a consistent method that the user can understand, is warranted. One difference to note in the model discussed here and the typical model is that the credit card model uses credit - you don't need to have money sitting on your credit card for payments to go through - and many people (if not most) do manually pay their credit cards. So you could envision a model where multiple apps request charges and then a user can approve them at all at once at the end of each month. Apps could decide themselves how long to allow the user to go without approving. But maybe that's pointlessly carrying over the legacy mechanics. |
This is a neat idea.. I hadnt even though of encapsulating the TOS as a smart contract and linking it but it makes total sense!
Agree
I don't feel like it's better for the consumer in all cases. See the 'opt in ever month' vs 'opt out' models above
I agree!
The reason I ERC'd it is that I think this is a core enough piece of infrastructure that it shouldnt be written by a rent seeking ICO or token based model. It should be a core piece of the infrastructure.
This is interesting.. Thanks I didnt know about 0x doing this!
It scares me to have the contract approved for an unlimited allowance. I get that you can mitigate it by code reviewing the smart contract that it's called for the unlimited allowance, but I still think the trust model is funny. The other thing that
I have heard rumours of ETH being moved to being an ERC20 token, but am unsure of the status there. Does anyone know?
Could you articulate what you mean by 'price based withdrawals'? Do you mean $20 worth of token X every month? I had not envisioned this protocol being priced based, if thats what you meant. Only use case I had envisioned being in scope was "X tokens per TIME_PERIOD", aka "10 tokens per mont"
Yep! My only two core beliefs so far are that I dont want to see a rent seeking token powering this (so thats a vote in favor of being built into Ethereum) and that the system shoudl be trustless (which I think could go eitehr way.)
yes! it fundamentally aligns incentives between user and dapp.
Interesting, I had not though of this. Will noodle on it. |
I like the idea and the premises. Industry does have come to like steady cash flow streams vs one-time payments. The second benefit is that such feature will enable businesses processes common to e-commerce and sales. I would argue it is best practice to enforce some ground rules in the lowest protocol where that makes sense vs the dapp layer. One situation to be avoided is an intermediary could make payment decision on behalf of a customer. The person who is paying should be the one committing the payment directly. |
It's true, but unlimited allowances make for a much better UX. That's why with the new #777 standard, unlimited is the only sort of allowance supported (via authorizeOperator). In reality, it's not unlimited, because there are very strict rules coded into the contract about when tokens can be moved. It works best with a shared contract (like 0x), that you only need to audit / approve once, rather than everyone deploying their own. |
Consider: Pre-paid vs post-paid. Pre-paid puts trust in the service provider, post-paid puts trust in the subscriber. Post-paid allows for things like pro-rated subscriptions on cancellation and some other UX benefits, but subscribers generally can't be trusted compared to service providers (one to many relationships tend to by much more Sybil attackable by the many vs the one). |
Hi! It's not clear to me what you mean by 'pre paid' vs 'post paid'. Are you using a different verbage vs opt in/opt out verbage that I used in the OP issue desc? |
Here are a few thoughts: I think that price should be out-of-scope for this standard. This feels a lot like scope creep to me and doesn't need to be part of the core API. Ideally whatever protocol rules are decided allow for this type of behavior. From the subscriber's side:
From the providers's side:
And to think a bit about protocol: Building on the token ERCs seems valuable here since they already setup primatives for transferring and approving. What's missing is the concept of time based approvals. I think that we can get very close to hitting all of the use cases above with the following API Subscription APII think we need the following minimal API
These probably have An ERC20 token based subscription contract.With the above, we can now think about what a subscription paid in ERC20 tokens might look like. A minimal implementation would require the following fields.
The Closing ThoughtsGiven the wide set of use cases for subscriptions and the wide array of different business requirements, I think this specification will be most useful if it sticks to trying to define an interface, and leaves the exact implementation up to the provider. A provider would either provide their own implementation of a subscription contract, requiring the user to fund the contract once it was created for them, or they might delegate to a 3rd party service which offers pre-built subscription contracts that fit their business requirements. |
I think most tokens are too volatile for people to be comfortable denominating subscriptions in, (e.g. all crypto subscriptions would've been cancelled last fall) but let's find out |
I'm not speaking on his behalf, but my read on it was that pre-paid means paying upfront for service and post-paid at the end of the period. Like how you have to pay your rent up front, but you pay your Netflix subscription at the end of the month. It's independent of opt-in/opt-out.
Excuse my ignorance, but why is this not viable to do with ETH? I love this proposal & have been thinking about it for a few months. It could really put the power in the hands of the consumer / customer - right now if I want to cancel my Netflix, I have to log in to my Netflix account or worse (e.g. get on the phone 😲 ). Rinse and repeat for any other poor choices I've made with my credit card info (e.g. my Knit-Wise.com subscription or my XtremeNitroShred.com subscription). The way I've been thinking about this is as follows (keep in mind, I'm an ETH hobbyist, not a professional solidity dev):
The assumptions this is based on:
Some things I thought might be worth considering:
|
one particular token comes to mind which may prove to be an illustrative counter-example. Even if most are not suitable for this, it only takes a few that are stable and fungible to make it worthwhile. (my 2 cents) |
Heya everyone, dig this discussion a lot @owocki! Thanks for kicking this off. I'm the creator of StakeTree a crypto equivalent of Patreon. It's still early days, but I've got some pilot projects running to test market interest and there seems to be quite a neat demand for this. (I'm even funding myself through this!). I've thought a bit on this and tried some contract variants on how to make some kind of pseudo-subscription system. I'm a new solidity dev so there's still lots that I might miss here. To @owocki's point, on the merit of a subscription standard, I'm fully onboard with this. Having previously worked in SaaS, it's a massive industry and having subscriptions could be hugely beneficial for crypto projects. My naive implementation to get this working was to have a contract where funders can pool money into the contract and the beneficiary can then withdraw 10% from the pool every week. Funders can refund whatever is left of their funds at any time. For example, if they put in 1 eth, and two withdrawals have occurred, they can then refund themselves 0.81 eth if they want to or continue funding the beneficiary. See code here. There's an additional tokenization aspect I added which is unrelated to this discussion (it allows you to reward funders for their contribution). This implementation is sub-optimal in my view because it requires a big capital upfront cost for the subscription. 1 eth only generates 0.1 eth of "payment", then diminishes every week by 10%. Although this could be useful for a Patreon-style subscription where the exact funds aren't the issue, but rather that funds are there. In cases where an exact payment amount is needed, this doesn't work. I then tried to do a cleaner version where you could commit to X amount of ether over Y weeks. I called it X-Over-Y subscriptions. So let's say I want to use Netflix for 12 weeks, I can pay upfront and then the beneficiary can withdraw the allocated funds each week. However, I ran into gas cost issues very quickly due to iteration. In most cases, this was my concern technically with subscriptions on smart contracts. I was working on these before CryptoKitties arrived and then it was just barely plausible for gas costs, but soon, the network congested and it became incredibly unfeasible. (To reiterate, I'm not the best solidity dev here, so I might have missed something). I might be reading these wrong (please do correct me!), but it seems like @pipermerriam, @ptrwtts & @abunsen's possible implementations would require the provider/beneficiary (the project/person receiving the funds) to send a transaction for each subscriber. This kind of scalability might be solved in future, but at the moment, this has been a big blocker for me because of inherent costs and potential uncertainty regarding fluctuating gas price. This is also a tricky UX issue. If the provider runs a withdraw action on a front-end and triggers multiple transactions, what's the easiest way to have that run without someone sitting there signing each transaction? The other kind of scalability that iterates within a contract, let's say, all there's some kind of aggregation where all subscribers gather in one contract for the provider/beneficiary, could lead to gas limit issues. I solved this by using some math to calculate the totals for funders on the fly and only store how many withdrawals occurred and at what withdrawal they started their funding. But this might lead to the 10% issue, where all funders would have the pay the same amount. (I might look into this again in the future). At the risk of not letting this get too technical & sorry for being a bit late to this discussion. I'm in agreement that a common interface would be really amazing here, but the reason I go a bit deeper here is so that I can urge proposers to please consider the usability & scalability of a subscriptions standard as well. When proposals are put forth, can we also discuss scenarios of how it would work for 1 subscriber, 10 subscribers, 500 subscribers, 1000 subscribers etc. If it doesn't scale, any subscription can be trivially DOSd. Never mind the possibility of a sybil attack added on top of this. I'm hugely excited for this. I'd love to hear more thoughts here. And again sorry if I misunderstood some of the suggested implementations (y'all are all probably much smarter than me!). If either we create a scalable subscriptions standard on the smart contract level or we look at the core ethereum level, this will be huge. Thanks again @owocki! Let's do this! |
I'm not sure I'm fully convinced by the rational for the EIP. In fiat country subscription services are in fact highly regulated via amongst other things something called a "clearing house". It might be the case that a service provider eg "ClearETH" could be the intermediary between users and their subscription providers and solve much of this while not reducing a user's control. |
Regarding @pipermerriam's spec, it should be required that the |
I've updated my post to include this. Note that my spec makes no requirements on what the underlying implementation does in terms of functionality, so this was added as a "should" to ensure that implementers are aware of this use case. |
@nieldlr I think I understand your concerns, however, from the complexity/security/optimization/efficiency trade-off perspective, I think that a contract-per-subscription is the right choice. Providers can still batch their withdrawals which should have a noticeable effect on reducing transaction overhead. In theory calls to the |
@pipermerriam wouldn't a single shared contract be better than a contract per subscription? this way, you can have confidence around what it will do, without having to audit every single subscription you do. i'm guessing it would also be cheaper to setup, if you used a createSubscription() function instead of deploying a contract every time. it could either be one universal contract, or at least one contract per service (similar to tokens). |
@ptrwtts My preference for a contract-per-subscription model is fueled by the same reason that ENS uses stand-alone deed contracts. Since these contracts hold user funds, by keeping them in separate contracts you reduce the attack surface area by eliminating an entire class of attack since user's funds are not intermingled. |
I've implemented pre-paid "subscriptions" in dotta-license by setting an expiration time on an ERC721 token. At checkout, users select the length of time they want to pre-pay: When the token is issued, it sets an expiration according the number of "cycles" the user paid for. Users can renew at any time. My client-side app verifies that the token has not expired. (You could do this with a desktop app, mobile, or SaaS service.) Because the verification is client-side you can provide any sort of "grace" period you want, such as not disabling until it's been unpaid for a certain amount of time. Also, because there is a client-side app, I'm using that app for reminders when the subscription is near-due. From a sellers perspective, credit-card based subscriptions are be beneficial in that users are default-pay (for example, if they forget or just do nothing, you still retain the subscriber). Obviously, we don't have that in Ethereum today. For pricing, there is code that will sync a list of products and their prices. I update prices periodically to be reasonable within conversion rates. However, the downside(?) to this (optional) process is that a subscription's price isn't "fixed" (or grandfathered) to a particular price in ETH. I tell my customers that it they want a fixed rate, then they ought to pre-pay for a longer time period. There are interesting incentive dynamics here. The code is all open-source/MIT, including the contracts, commandline management tools, and React UI widget. |
I actually see this as a benefit. If you build in a short waiting period during which time your client could either quit your service (because the price you set is too high) or make a counter-offer (because he/she believes the exchange rate is not fair), then you actually have a model that might work. As it is, I don't like that only you can change the rate. |
I believe the schemes your both mentioning can be accomplished under the spec I proposed here. Please correct me if I'm wrong. |
Heya @pipermerriam, could you explain a bit more on how this works? I'm not quite familiar with batching and how this exactly works here. Eager to learn if this could solve our challenge. Again, from a purely practical point of view, having multiple tx costs to the provider is not scalable. My focus is primarily on people building up support from their communities/fans/supporters and this type of funding can be much smaller. Here's the income distribution on Patreon for example: My withdraw function is currently sitting about ~50k gas cost & back during the network spike in December/January I ended up paying $0.50 per withdrawal. https://etherscan.io/tx/0xe6e5534baee4a6d91c2d288dfb803199d0e1dcb8c3798162dc2a4bb11935a8df Back then I had about 20 funders, which means that if I ran a ~100k gas cost withdrawal for all of them, it would've cost me $1*20 = $20. This is unfortunately not a reasonable cost for a provider & I would call that a failure of Ethereum to be able to handle subscriptions and rather prefer using centralized providers like Patreon. I'm taking the extreme case here in terms of network congestion, but this is by far not the most extreme in terms of how many funders one could get for a project/app etc. It's just not a user experience risk that I'm comfortable with taking for an app/service I'm fully aware that we might need to make some tradeoffs here somewhere, but my hunch is that perhaps there's a different way to solve this. Eager to hear if batching (or any other solution) might solve this. Thanks for exploring this with me (and everyone else here!). I'm passionate about this, because I believe this opens up so many opportunities. |
I wonder if the optimal interface for there is certainly a tradeoff from an attack surface perspective, as it's a nice best practice from a security perspective to be able to keep funds for different subscriptions in seperate contracts to make each contract less of a honeypot |
Each user would have their own subscription contract. The naive approach would be to send 1 transaction for each subscriber, calling To batch these, you would do this with another contract layer. Here's a psuedo-solidity implementation. contract SubscriptionInterface {
function triggerPayment() returns (bool);
}
contract BatchTriggerPayment {
function triggerBatchPayments(address[] subscriptions) returns (bool success) {
for (uint i=0; i<subscriptions.length; i++) {
success = SubscriptionInterface(subscriptions[i]).triggerPayment();
if (!success) {
revert();
}
}
}
} This should save you It's still an O(n) cost, but it's reduced by an O(n) factor due to the savings on transaction overhead. Remember that true scalability is something that will happen at the protocol level, after which most of this gas accounting and optimization should matter way less. |
Can't this be done by signing some time-locked erc20 cheques somehow? Ideally the user should sign a message saying "after block X, transfer N tokens to Bob". They could do it 12 times for all months and renew the subscription next month. The scope and how to do time lock cheques is what should be is debate in this ERC. |
@PaulRBerg good to meet you. wanna join our weekly call (thursday mornings) and nerd out about this? |
Sure thing! Emailed you now. |
there's a weekly call ? very much eager to listen in :-)
…On Tue, Jul 17, 2018 at 11:31 PM, Paul Berg ***@***.***> wrote:
Sure thing! Emailed you now.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#948 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ARXoQE-5XY9bz5zZmWxwFYVz681G7lLpks5uHlekgaJpZM4S6OSD>
.
|
yes. contact @androolloyd for the weekly call. we are all hanging out at gitcoin.co/slack in the #proj-subscriptions channel too |
Just published the research I and @mmilton41 have been doing on Chronos, a protocol for continuous, recurring payments. Although it's tangent with the ideas expressed in this chat, the focus is instead on infinitesimally small payment intervals (minutes, hours, rather than months). We mentioned ERC948 and the projects working on it in our draft white paper. Still many things left to cover (we're using Plasma), but aiming to start coding soon to test our assumptions. Feel free to join the discussion here: https://ethresear.ch/t/chronos-a-quirky-application-proposal-for-plasma/2928 |
I've had an idea that the subscription model can be used for crowdfunding. In some cases it's a better fit than the ICO. For example, I want to create a service (a Dapp). I can sell subscriptions for the service to fund the development. Maybe even investors would buy subscriptions to the future service as an investment, to sell them later to customers for a higher price. Looking at this use case subscriptions are like NFT's. |
@leonprou you're going to really enjoy an upcoming post from Groundhog, we've been working on this model for a few months now. |
I see this is already a fairly old thread. Has this idea been already discussed: Build (an ERC20) token that allows for "streaming transfer", that is, a stream of value at a set rate. It would perhaps be similar to time-locked cheques, only the time-lock is checked on every transfer (normal or "streaming" kind) so that tokens that "don't belong to you anymore" can't be transferred.
Benefits:
It would be straightforward to check if the account still can pay for its subscription(s). What happens after the account dries up would be outside the scope of the specification, but at least the vendors would have simple ways to follow if they're still getting paid. If the particular ERC20+streaming would be tied to a service with limited number of different types of subscriptions, the "end timestamp" of currently active subscriptions could be calculated and emitted upon each transfer. This would make it even simpler for vendors to follow if they're getting paid: instead of polling, they could listen to update events by the subscription ID. Withdrawing could even be done so that existing approval functions are augmented to show tokens belonging to a vendor as approval from the ERC20 account, and vendor could then simply Implementation scope and challenges:
If this idea sounds appealing to anyone, I could knock together a simple PoC implementation. If this already has been discussed and/or implemented, I'd love to hear about it (please link to URL). If the functionality has been implemented already in another form, that's interesting too. I skimmed through the 8xprotocol white-paper, and it proposed an interesting layer 2 solution. I'm just wondering here if a simple (it's relative...) smart contract could also do. EDIT: Chronos has an implementation of "token streams" EDIT: @d10r mentioned their project Artis that implements token streams called Streems |
@jtakalai yes, I've done a PoC a while ago, the code can be found here. PS: Vitalik also seems to have discovered the topic: https://twitter.com/VitalikButerin/status/1093091291066294272?s=19 |
Follow up to my previous comment: Proposal for Streaming Token Standard with example implementations linked in Implementations section. |
There has been no activity on this issue for two months. It will be closed in a week if no further activity occurs. If you would like to move this EIP forward, please respond to any outstanding feedback or add a comment indicating that you have addressed all required feedback and are ready for a review. |
This issue was closed due to inactivity. If you are still pursuing it, feel free to reopen it and respond to any feedback or request a review in a comment. |
Dear Colleagues,
the end of an era, but not the end of this idea. Here's to hoping each of
your's workarounds end up as a standard for this soon !
Warm Regards,
…-Joseph.
On Sun, Jan 2, 2022 at 12:11 AM github-actions[bot] < ***@***.***> wrote:
Closed #948 <#948>.
—
Reply to this email directly, view it on GitHub
<#948 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AEK6QQELYYEDBG24BVNTURLUT6C3VANCNFSM4EXI4SBQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
I tried to find the status of this proposal on the ETH page https://eips.ethereum.org/all and I couldn't. So kept googling and I found this. Sad to see that is closed and no more in discussion. I don't understand how such good idea can't be on the queue to be implemented. Any chances to reopen this? |
Hi eveyone, Largely inspired by this idea, I create Subs , a protocol for making recurring onchain payments that can have different uses cases such as subscriptions, DCA, recurring donations or others. Website : https://subsprotocol.com/ Please, take a look, am open to discuss if needed. |
@specialOne-coder This is absolutely incredible what you have created. Tried to reach out to you on Twitter but unsure if there is a better way to contact you? |
I think for eth or erc20 any subscription payments, this can be done with smart contract wallets for consumers and having special contracts aka SubscriptionModules enabled where service provider can pull payments |
But in this case the user should create a new smart wallet right? |
For eth yes, but for ERC-20, smart wallets is not needed, just approval can do the job. And I don't think anyone is keen on paying for subscriptions with eth, unless it's a specific use case, like paying off a debt every month. |
Unlimited approvals to a third-party contract can't be good practice tbh. |
Could you briefly describe pros/cons, fees, networks support, etc.? |
Hey, let's disuss it on
Hey let's discuss it. Here is my telegram : @FolkoK |
I am opening this ERC as a means of discussing (a) the merits and (b) the viability of creating a standard way of managing recurring payments on the blockchain, both (1) for tokens, and (2) for Eehereum.
Merit
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).
For these reasons, I think it's worth talking about the viability of creating a standard way to do 'subscriptions' on Ethereum. I'm envisioning an
From UX standpoint, it would be pretty nice if you could manage all your ethereum-based SAAS subscriptions from one service like an on-chain keychain, if privacy was respected.
Viability
Opt in every month model
This is already viable if a service were to send an email (or other notification) to a user to every month sign a transaction.
But it creates a lot of churn in the subscriber base because the steps of
is a lot of friction for the user.
It is also suboptimal from a cash flow perspective from the business, because the trickle of exchange of a value to the user and revenue for the business requires each party to reaffirm their relationship every month.
In a world in which there are 100s of Ethereum based dapps, it would simply be untenable from an attention standpoint for a consumer to manage all of their subscriptions in this world.
Opt out model
For the above reasons, I think it's optimal for Ethereum to support opt out subscription models. I am defining an opt out subscription model as
price
worth of ETH (or tokens) withdrawn everytime_period
byservice_address
.service_address
may removeprice
worth of ETH/tokens everytime_period
. If those tokens are available and the users consent is active and its been at leasttime_period
since last withdrawal, then the tx will be successful. If not it willthrow()
.Case Studies
Take the case study of Adobe Creative Cloud. Prior to 2013, you had to pay $1000 for creative suite, and it was a massive barrier to entry. Now you just pay $40 per month, and you can learn the software and continue to pay if you use it. And Adobe can manage their cash flow over time.
Or the case of Amazon Prime. For $80 per year, one can simply (1) not have to pay shipping for their goods (2) receive a ton of benefits related to their content. And now amazon can do revenue forecasts more accurately because they're managing a consistent voume of cash flow.
Technical Viability
Right now, it is not technically viable to do opt out recurring subscriptions on the blockchain. The best workaround would be to present a user with an
approve(x)
where x = price * n, where price is the monthly price of the service and n is a number of months, and then calltransfer(x/n)
every month or so.Until (and if) ETH becomes a token, it would not be viable to do this at all with ETH.
Proposal.
I am not at a point yet with this idea where I feel comfortable presenting an interface. A discussion on (a) merit should precede the discussion on viability and proposal design.
My only strongly held beliefs for the 'proposal' stage of this ERC at this point is
👋
@owocki and the @gitcoinco team.
The text was updated successfully, but these errors were encountered: