Open Value Sharing (OVS)

Hello everyone, Demergent Labs has recently finished its initial draft of the Open Value Sharing (OVS) specification, along with an initial MVP implementation that is live (but turned off by default) in Azle.

From the spec:

Open Value Sharing (OVS) is an open protocol for automatically sharing monetary value with software dependencies.

OVS enables consumers of software dependencies to automatically pay for their use while minimizing or eliminating the friction involved. Though not restricted to open source software dependencies, one main goal of OVS is to enable a new open source native business model, facilitating automatic revenue streams to open source projects without requiring changes to their licenses.

OVS embraces a number of core ideals:

  1. Minimize or eliminate consumer (payer) friction
  2. No changes required to existing dependency licenses
  3. Voluntary participation from consumers and dependencies
  4. Flexibility across platforms, payment mechanisms, sharing heuristics, and other parameters
  5. Heuristics over perfection

I would like to ask the community to read the spec and offer any feedback.

@icpp Will be working on the implementation for the C++ CDK. @skilesare is working on similar things focused on the Motoko community.

Azle will go through an MVP phase with OVS turned off by default as a testing phase.

The plan is to eventually enable OVS by default for all Azle canisters, thus creating a consistent stream of revenue for libraries included in Azle canisters.

I also have three things to ask for DFINITY to consider:

  1. Allow canisters to query their own cycle burn over a period of time (my understanding is that this is in progress)
  2. Incorporate OVS at the application layer into Motoko and the Rust CDK (happy to do a PR to the Rust CDK)
  3. Incorporate OVS at the protocol layer, which might provide the most elegant solution

Letā€™s make open source its own industry starting on ICP!

13 Likes

For OVS to succeed, it must be compelling for both consumers and providers. Clear incentives and benefits need to be communicated to both parties. Additionally, strategies to drive initial adoption, such as pilot programs or incentives, might be necessary.

Also the economic model underpinning OVS should be robust. Questions around how value is measured, distributed, and adjusted over time need clear answers. Additionally, potential impacts on smaller or less popular dependencies should be considered to avoid unintended negative consequences.

I think itā€™s compelling enough for dependencies, they will earn ā€œfreeā€ money. They just have to pop their configuration into their project and set up a means to receive the money. I feel like thatā€™s solved.

Consumers is a different story, but the spec is very clear on this: consumers must not be required to do anything for the payments to stream. They would have to actively turn off OVS to stop the payments from streaming.

And to that I would say, from the spec:

To the first concern, ideal 3 does allow for consumers to choose to turn off OVS. The rebuttal is that there is a cost to turning off OVS, and it may be higher than the cost of leaving it on. Leaving it on costs money. Turning it off costs mental effort, team time, and the conscious decision to not give back to open source. There could also be public pressures that arise incentivizing companies to continue to give back, especially if it was the default setting and a conscious decision to not give back.

Also the economic model underpinning OVS should be robust. Questions around how value is measured, distributed, and adjusted over time need clear answers. Additionally, potential impacts on smaller or less popular dependencies should be considered to avoid unintended negative consequences.

Can you elaborate? Ideal 5 addresses this. I donā€™t think it needs to be very complicated. Burned Weighted Halving I think will be a great heuristic that will generally work well, and if it doesnā€™t the spec allows for implementations to overwrite individual weights for dependencies, controlling their payouts.

The dependencies canā€™t control any of this though, they are at the mercy of the consumer. But with sensible defaults I hope we can learn over time. The spec is flexible enough I hope to allow various heuristics to arise over time.

Great idea. It looks like the model proposed is to implement a consumer -> [deps] relationship for canisters that opt-in.

With visibility in mind should we also consider a model where the relationship would be consumer -> OVP dapp -> [deps]. The OVP dapps could bring a lot of benefits to OVP in terms of metrics, visibility, governance (which in my view is needed for such a project to work as scale - I know some people disagree here).That could also be implemented we a fully decentralized smart contract.

1 Like

What is an OVP dapp? And even without knowing what an OVP dapp is, I believe the spec and even Azleā€™s implementation (almost for the implementation) is flexible enough to allow the payments to flow to an intermediary. The dependency would simply specify that in their config using the custom section.

Cool idea! I really think that such a minimal friction approach could be a way to get more reliable funding for projects!

For economic concerns I think it would be great to add a section about transaction costs since this is a huge concern with micropayments. An idea I had for payment channels with fees larger than deposit_cycles is that you could randomly (or round-robin, or whavever) choose one or a few dependencies to pay every interval.

We discussed your proposal yesterday in a small group. TLDR: we really like the idea, but before devoting too many resources (e.g. protocol support) weā€™d like to see it working in practice

Itā€™s not in progress yet, but on the shortlist of features weā€™d like to pick up soon :tm:

We thought it would probably work a bit better as a separate crate (just like ic-cdk-timers, which probably would be a dependency of an OVS crate).

OVS (at least as far as we understood) can be implemented in application space, so weā€™d prefer keeping it there, at the very least until itā€™s proven its use. Nobody was against protocol support in principle, but especially at an early stage weā€™d like to see some very good reasons why it canā€™t be solved on the application layer

1 Like

So glad you took a look!

Iā€™m not too concerned about this at the moment, the default period is one day, and especially at first there arenā€™t going to be that many dependencies to pay out. Even with 100s of payouts it donā€™t believe it used that many cycles. I didnā€™t do a robust set of recorded benchmarks for the MVP, I just got a feel for it.

That being said the best solution I imagine will be ICRC batch payments on the cycles ledger no?

So awesome to hear! I agree, we should prove this out first at the application layer. Azle, Kybra, and icpp will all have implementations to prove our the idea.

1 Like

It can be a separate crate, but it MUST be included by default in the Rust CDK so as not to violate ideal 1 of OVS: Minimize or eliminate consumer (payer) friction

If it isnā€™t included and turned on by default in the Rust CDK for example, I believe the odds of the consumer turning it on are greatly diminished, as explained in the spec.

Iā€™m not too concerned in ICP land, but since you talk about other protocols and currencies I think at some point it will be a concern. Maybe we are also thinking about different scales? I was thinking e.g. about some hobby project that burns through 1TC per month. If you burn through dozens of dollars worth per day itā€™s a very different story.

:person_shrugging: Define ā€˜bestā€™. A deposit_cycles or wallet_receive call costs O(100k) cycles. A cycles ledger transaction costs (at least for now) 100M, and it is billed to the receiver. OTOH itā€™s much more convenient because it has an indexer attached, thereā€™s no need to maintain the receiving canister, etc.

1 Like

I agree it should start at the application layerā€¦the worst part about doing this at the application layer is the timer and payouts. Each canister must keep a timer going at all times, and will have to have an update call with multiple (maybe collapsed to one with batch transfers) cross-canister calls to execute the payments.

The protocol layer implemention could do away with canisters having this looming timer and could possibly remove the payments from the canisterā€™s execution queue, and could maybe even burn and mint instead of doing payments. I feel it will be more elegant and less heavy in the canister, it just feels better.

I hope we get some good traction at the application layer first.

1 Like

The total amount burned, at least for the Burned Weighted Halving heuristic, doesnā€™t really matter does it?

No matter how much is burned the number of batches and payments will be the same. If the period is 1 day and there are 10 registered dependencies then there will be 10 payments per day no matter the total burned between periods (assuming the total is large enough that each payment has a non-zero amount to be paid).

Good to know! The dependency can choose their preferred method, we will document all of this.

Thatā€™s my concern. Here Iā€™m trying to deposit 10k cycles to the cycles ledger:

āÆ dfx canister call --ic um5iw-rqaaa-aaaaq-qaaba-cai deposit "(record { to = record { owner = principal \"$(dfx identity get-principal)\"} })" --with-cycles 10k --wallet $(dfx identity get-wallet --ic)
Error: Failed to do wallet call.
Caused by: An error happened during the call: 5: IC0503: Error from Canister um5iw-rqaaa-aaaaq-qaaba-cai: Canister called `ic0.trap` with message: The requested amount 10000 to be deposited is less than the cycles ledger fee: 100000000.

and with --with-cycles 101M it will succeed, but the account only gets credited 1M cycles, even though it should have earned 101M

Another idea is to let dependencies specify the minimum payout amount or frequency that they consider ā€˜worth itā€™. I would personally be happy to receive payments once a month instead of daily if it means that I donā€™t have to pay >10% in TX fees

Anyways, Iā€™m talking pretty low level details here. I like the general approach and am looking forward to seeing it play out

1 Like

This is not exactly what you are discussing, but it seemed related, and I wanted to mention my interest in building a related IC-app canister. It would function similarly to state-channels in Bitcoin or plasma in Ethereum. The purpose of this canister is to serve as a central API tracker for fees associated querying with various canisters. Rather than making immediate payments, an account has a total balance, and with each query the amount owed to that canister is updated. A user can only make calls their balance exceeds the amount owed to the subscribed APIs. The API provider can then be claim their revenues at a frequency which is worthwhile (or use it for calling other APIs).

In general, having money sitting in an account is wasteful. Therefore, having a central mechanism for multiple APIs would be more efficient. In Ethereum, ā€œcapital efficiencyā€ us a common mantra. Having a single debit account is more efficient. Furthermore, we could also design the canister (as a user option) to invest resources in a protocol like Maker/Compound when that comes to fruition on the IC (or using cross-chain capabilities ā€“ which would come with much higher withdrawal costs).

There is a good bit going on in this post and Iā€™ve been scurrying around to get most of it ready. It is all far from ready or settled, but I figured Iā€™d put it out there as working code outperforms just talking about it. All of this should be considered very very alpha and if you decide to use it, you should not rely on it as mission-critical and Iā€™d imagine a good bit of your value may be at risk if you just let it sit there.

math-calculate

TLDR: You can add OVS sharing to your Motoko libraries now and have them send cycles to a wrapped cycle ledger to retrieve later.

ICRC-85 - Open Value Share Implementation Standard - Predraft

This is not even a complete draft, but Iā€™m putting it out there for discussion. Most of what is included is optional. Iā€™ve tried to write the motoko parts as that is what Iā€™m familiar with and Iā€™ve tried to pull the examples in the current implementations of OVS that @lastmjs has in Azel, but I probably got it somewhat wrong. Weā€™ll need to add in the Rust and C++ parts(maybe kybra as well?)

This is specific to the IC and doesnā€™t comment on implementations elsewhere.

Link: ovs-ledger/icrc85.md at main Ā· icdevsorg/ovs-ledger Ā· GitHub

It defines and suggests the following things:

  1. Shared Custody: Optional - It proposes a scheme and compatibility for transmitting OVS cycle shares to a ledger that wraps the cycles and holds them for retrieval/withdrawal later. The goal here is cycle cost reduction, call count reduction, centralization of statistic gathering for publicity, and showing that this is a viable way to collect value, and proposes a way to secure cycle jacking via namespaces. Basically, you can tell OVS heuristics that youā€™d like your cycle sent to a ledger along with where youā€™d like it stored(a principal(default account), an account, or in a namespace reserved account that only you have access to(more on this later). If you donā€™t want to use shared custody then you just point to whatever collection canister you want that implements your collection mechanism. The heuristic code should be smart enough to batch up the payments going to same shared custody canister and send those together. The canister mints the wrapped cycles and holds them there in the developerā€™s account. Note: This functionality could be easily added to the ā€œofficialā€ cycle ledger but for now there is a temporary ledger deployed at q26le-iqaaa-aaaam-actsa-cai. You can also deploy your own or fork it to do something different(more later)
  2. Azel implementation instructions that shows how to add the openvaluesharing.json file in your project directory, how to override it with an entry in dfx.json and the available settings.
  3. Motoko implementation. It suggests that we add something to mops(attn @ZenVoich) to make things like the Burned Weight Halving easy to add and sets some coding standards for how to add OVS configurations to you libraries and how to override them from your projects. It proposes a simple import file pattern and suggests a common environment parameter best practice for overriding and configuring your OVS setup (including default behavior if no heuristic is defined) and how to hand control back to a heuristic from you library if the user provides an override.
  4. Defines the endpoints that heuristics should send cycles to, either icrc85_deposit_cycles_notify (oneshot) or icrc85_deposit_cycles(trusted) and takes a parameter of vec { record{ text; nat; }} which allows shares to easily be split according to the the share of total nat values in the batch. The inclusion of text can allow for tracking a namespace of the library so that developers can track what libraries they are getting payments for. If it is left blank it just goes to the canister the share is sent to.
  5. Optional Queries: Defines optional query functions that may be useful for reporting and for looking up the expected account of an unclaimed namespace.
  6. Block Schemas: Defines a block schema for withdrawing your cycles from the ledger so that the transaction log contains the full details of where to find the transaction on the actual cycles ledger.
  7. Other Standards: The shared custody solution can also optionally use the ICRC-75(identity standards), ICRC-86(namespace claim standard), and ICRC-84(Deposit/withdraw standard) - All of these standards are drafts and we are a good way from finalizing or even addressing some of them, but they are referenced to spark discussion.

ICRC-86 - Domain Claim Standard and manual implementation

This is also a very early draft and proposes a standard for manually and eventually automatically claiming domains such that others canā€™t ā€˜name jackā€™. It provides a workflow for claiming a namespace like com.foo.libraries.coollib with the caveat that you need to own the ICANN name fool.com(or have access to its DNS). There is also a suggestion for a non-centralized naming schema.

Link: ovs-ledger/icrc86.md at main Ā· icdevsorg/ovs-ledger Ā· GitHub

The intention here is to allow developers to start broadcasting cycles to some place they know they can retrieve them without having to jump through a bunch of hoops. I can start sending cycles to a shared custody ICRC-85 ledger with the namespace org.icdevs.libraries.killerlib right away and no one but me can claim them. And I donā€™t have to go through the claim dance until there is enough value there to bother with.

In the current deployed contract, the ICRC-86 claim will issue you a random key to put in your DNS and then ICDevs can approve you to own that namespace. Once claimed you can add a pointer for where you want funds from that namespace to go(more on that later). Eventually, this can be automated via httpoutcalls to query a couple of different DNS registries.

ICRC-84 implementation

@timo has suggested a nice Deposit and Withdrawl standard at ICRC-84 [WIP]: Deposit and Withdrawal Standard for ICRC-1 tokens Ā· Issue #84 Ā· dfinity/ICRC Ā· GitHub which suggests how to standardize depositing and withdrawing tokens from services like DEXs. It may have been overkill to include it, but it was a good excuse to try to implement it. We only use the withdrawl side of the standard since deposits are all done via sending cycles with a standard mint command. You can also withdraw just by burning and weā€™ll send the cycles to the cycles ledger at the from address, but it is nice to have some code to look at that does what Timo is trying to achieve.

ICRC-75 Implementation

We took this opportunity to do the first implementation of the ICRC-75 standard that we have written for the DAOs project. This standard allows you to manage the mapping of a namespace to a list of Principals, Accounts, Values, or sub-lists. When you pair 75 with 86 you get a powerful way to declare and manage lists of things on the IC and we can plug these lists into things like verifiable credentials, jwts, subnet certificates, and other functions as well. We are simply using the standard to map a claimed namespace to an account so that if your OVS implementation sends cycles to org.icdevs.libraries.icrc75, ICDevs can map that namespace to their desired account. To claim an namespace you need to control the ICRC-86 reservable domain.

Link to draft standard: ICEventsWG/draft_proposals_current/icrc75draft.md at main Ā· icdevs/ICEventsWG Ā· GitHub
Link to motoko implementation: GitHub - icdevsorg/icrc75.mo: ICRC-75 for Motoko

OVS Ledger

As mentioned before, this functionality could/may migrate to the actual cycles ledger. In the meantime weā€™ve taken the opportunity to implement a number of experimental ICRCs to test their robustness and usefulness. Weā€™ve deployed an OVS ledger that you can point your libraries heuristic at to collect cycles. You could of course point to your own cycles wallet that has a deposit endpoint, but by using the OVS ledger weā€™ll get community-wide statistics about the volume of cycles weā€™re distributing via open-source software.

Codebase: GitHub - icdevsorg/ovs-ledger: Open Value Sharing Ledger
Deployment: q26le-iqaaa-aaaam-actsa-cai - https://dashboard.internetcomputer.org/canister/q26le-iqaaa-aaaam-actsa-cai - It is an ICRC1/2/3/4 ledger with the 85/86/75/84 endpoints to provide a robust cycle claim and tracking infrastructure.

ovs-fixed

This is a Motoko implementation of a fixed heuristic that you can use in your libraries if you want a default OVS sharing pathway. This heuristic will let you easily implement something like ā€œSend me 1XDR of cycles a month unless the users calls my functions X number of times and then send me 2XDR a month. If they override this behavior with a different heuristic, notify that heuristic, and if they turn OVS off, just continueā€

Link: Mops ā€¢ Motoko Package Manager
Implementation: You can find an example implementation of the library in the ICRC-75 implementation at icrc75.mo/src/lib.mo at 9218d753b3ebc5cadde0ef19ac5c0ab77fd7eeee Ā· icdevsorg/icrc75.mo Ā· GitHub

(Yes, this means that the OVS Ledger sends itself cycles for use of the ICRC-75 library)

star-wars-circle-is-now-complete

This is all a super long way from being complete and needs further discussion and modification. Jump in and letā€™s discuss.

6 Likes