Completed: ICDevs.org - Bounty #17 - A DAO for Cycles - $10,000 - ht: cycle_dao

I think we would have to carefully consider the consequences, also together with the ledger team that has maybe already thoughts on that.

So are you planning to use the SNS canisters for your project? And will you anyway use the code that we provided but not necessarily follow all the upgrade paths that we will establish for the Carbon deadline?
If so, I think just setting the account on initialization is a good solution.

I think we defintly would like to be able to do that.

We should be able to use the SNS governance canister from the Carbon milestone (the one that sets itself as the minting canister). The only thing is that we won’t be able to set the governance canister and the CyclesDAO to mint the same token.

But I think this problematic is not inherent to the SNS. @skilesare Correct me if I’m wrong, but we assumed with the design of the CyclesDAO that it would be possible to have two canisters (the CyclesDAO and the governance ones) that could mint the same token, but right now the token standards don’t support to have more than one minting address. I think at the end the choices are:

  • accept CyclesDAO canister and governance canister can only mint different tokens
  • have a mint function on the governance canister, and the governance would keep a list of principals that are allowed to mint tokens through it
  • have this logic in an intermediate “access control” canister that manages the minting rights, and governance and CyclesDAO would interact with this intermediate instead of the ledger/token
  • push to update the token standards to be able to have multiple principals that could mint the token

Thanks for the clarifications!
Just to make sure we are in agreement, let me comment on the proposed solutions:

  • accept CyclesDAO canister and governance canister can only mint different tokens

I think this would work with the SNS as it is planned (although to be honest I am still not sure I fully understand what the required functionality of the system is and thus if having two tokens is something that makes sense). Probably this would mean that one has a SNS ledger and on top of this another ledger cansiter that is just also controlled by the SNS?

  • have a mint function on the governance canister, and the governance would keep a list of principals that are allowed to mint tokens through it

This will not exist for the SNS from Carbon deadline and is not explicitly planned. It would require a change in the SNS governance canister that should be considered carefully. If not done right this opens the SNS up to dangerous attacks. Especially, I assume these principals would all have to be SNS controlled, so this might have to be enforced.
What could be done with the SNS currently is to add a new proposal type that is allowed to mint tokens on the ledger when the proposal is adopted, but I assume this is not what you are looking for.

  • have this logic in an intermediate “access control” canister that manages the minting rights, and governance and CyclesDAO would interact with this intermediate instead of the ledger/token

As long as this new special canister is set to be the minting canister, this might work with the SNS canisters. However, it might not work with the “out of the box”-SNS that is planned for Carbon where SNS governance might be set to the minting canister (as mentioned, the reward design is under way and will be discussed with the community next week). In any case, I want to reiterate that this would have to be designed extremely carefully to ensure that the minting of tokens is controlled in a decetralized way and that the end-users also have to possibility to verify this fact.

  • push to update the token standards to be able to have multiple principals that could mint the token

As you say, this would require changing the SNS ledger. Again, we would have to carefully assess whether this is actually secure and advisable.

These are just my spontaneous thoughts on how I think the different solutions relate to what is currently planned on the roadmap. Hope that helps a bit!

1 Like

I am a bit lost on what function does what. Can the function wallet_receive only mint the fungible tokens in exchange of the received cycles ? If not, how do I know which NFT(s) to mint in exchange of the cycles ?

On ConfigureDAOCommand(#DistributeBalance), shall the CyclesDAO transfer or mint the token?

In my current implementation, I assumed:

  • Only DIP20, EXT(fungible), Ledger standards can be set and then used to exchange cycles in exchange of freshly minted tokens (no NFT)
  • ConfigureDAOCommand(#DistributeBalance) performs a transfer of the given token (one of the six possible, NFTs included)

The idea here is that if you contribute cycles you will get some dao tokens. Perhaps you could set this up to lint nfts, but that wasn’t the original intent.

This is only needed if the dao ends up with a balance somehow. Maybe the main token wants to take .5% of every transaction and send it to the dao so the dao can distribute it to developers. Just an example.

1 Like

Ok thanks, I think I’m doing the right thing then.

I think I have finished with the development besides:

  • some minor blockings/notes: everything is written in the readme. I am waiting on your feedback to work on these.
  • the implementation of the NFT_ORYGIN standard: last time I checked I could not find the candid/wasm files for the NFT token, but I’m gonna ask on the forum.
  • a phylosophical question: currently the cycles DAO can be configured with any principal as governance, which can be a single individual or an actual DAO. IMO it’s nice to have a separation of responsabilities per canister, and it allows a broader usage of the CyclesDAO. The drawback is that the frontend does not allow to add proposals, or to see their states - it only shows accepted proposal (i.e. actual configure calls). Also that makes the name CyclesDAO a bit misleading, because it’s possible to involve no DAO at all.

I would like to discuss two points:

  • one limitation of the current architecture is that the DAO cannot mint the same token as the CyclesDAO. IMO if we make the “CyclesDAO” configurable with any DAO, it’s a bummer to have this limitation. I think it could be solved with this architecture:

CycleSDAO

The CyclesDispenser canister is basically be the current CyclesDAO canister but instead of directly doing the mint it calls MintAccessController.mint().

The MintAccessController is a simple canister that is configured with a token to mint. On configureToken, it verifies if it owns the token. It keeps a list of authorized minters that can be added by the admin only. On mint(), it checks if the caller is authorized, if yes it mints the configured token.

The DAO can be any DAO that has the capacity to execute proposals as canister calls (like the BasicDAO from the examples). It can be used to call functions on the CyclesDispenser, the MintAccessController, or anything else. Which brings to my second point:

  • if we keep the CyclesDAO configurable with any DAO, IMO it does not make a lot of sense to have a function configure(#Distribute) because the DAO could directly submit a proposal to distribute some token itself, it does not need to call another canister to do that.
  • In walletReceive, there is no absolute guarentee that after the cycles have been accepted, the minting of the token cannot fail. In this case the loses his cycles and receive no token in exchange (see main.mo:143)

Maybe we should wait to accept the cycles until after the mint? In addition, the mint may have a cost and we might want to subtract the mint cost from the cycles? Might be a good use of the cycle calculation API?(ok to wait to another phase for this).

  • In distributeCycles, if one call to fillWithCycles function traps, it will prevent other allowed canisters from receiving cycles. (see main.mo:232)

Possible solution: When this is called have deque that is checked…if it is empty, fill it with items from the triemap. Cycle through the deqeue and before you call the item, move it to the back. If it is successful, remove it entirely. This way if there is a trap and the function fails, the committed items will be removed and you can just pick it up again on the next call. You’ll have to handle an permenatly failing item…maybe with a time-out? If the queue is over 5 minutes old it gets blown away? May need to think through this a bit more, but perhaps something along those lines?

nft_origyn

I’m finalizing it right now…I’ll try to get it to you asap…should be straight forward.

  • a phylosophical question: currently the cycles DAO can be configured with any principal as governance, which can be a single individual or an actual DAO. IMO it’s nice to have a separation of responsabilities per canister, and it allows a broader usage of the CyclesDAO. The drawback is that the frontend does not allow to add proposals, or to see their states - it only shows accepted proposal (i.e. actual configure calls). Also that makes the name CyclesDAO a bit misleading, because it’s possible to involve no DAO at all.

I’m not totally sure I follow. Why can’t the front end add proposals? Because it isn’t the governance principal?

100% agree on this principle. If you want to work up a simple controller it would be great. At Origyn we have minting_canister that acts in this way so it is likely a good pattern to at least describe in the read me for people that want to implement it. It can basically be a relay.

I can do that, it’s probably safer this way, but now there is a small risk that the amount of accepted cycles returned from ExperimentalCycles.accept is different than the amount passed as argument. According to the doc, it can happen if “less is available or the canister balance limit is reached”. If less is available, I guess that should never happen if we deduce the amount from ExperimentalCycles.available. If the canister limit is reached: this I don’t know where that limit is defined, but we should make sure that we cannot set a cycles exchange config that goes over that limit, otherwise once the limit is reached it’s free mint of tokens for everybody that call walletReceive.

Yes! I’m not sure to understand the timing thing though. But having an intermediate deque to monitor with which canisters to resume if the previous call to distributeCycles ever traps could work on its own.

Well I’m not sure what final product you expect. Do you prefer:

  1. a frontend specific to the CyclesDispenser canister. This frontend does not do anything DAO specific, it’s pretty much readonly (but maybe allow to call walletReceive, using plug or stoic ? is this something you want ?).
  2. same as 1. + another frontend specific to the BasicDAO (that btw I’m gonna have to fork and modify, I just realized that it needs to use a real token :clown_face:). So if the user ever decides to use another DAO that the BasicDAO, it still can access the CyclesDispenser frontend.
  3. a single unified frontend that uses both the cyclesDispenser and BasicDAO canisters, but if you decide to use your own DAO instead of the BasicDAO, the frontend wouldn’t work.

Cool! Then I know what to continue with :slight_smile:

I think you are right. We probably need a two-phase commit that makes things harder. You could record the transaction in a log, add the id of that log to a data repo(probably a Trie) and then when the mint succeeds…take it out. That way if it fails, you can add a retry function that takes the log ID and retries. I guess you’d need to expose this list via a function as well so people can query if they need to retry or not.

Think about this more, you probably need some kind of configuration that is a max_remote_calls anyway. If you have too many servers you will always overrun the cycle limit. You could return a variant that is #result(), #eof() and call it until it gets to eof.

I think I want this but without the limitation of something not working. Can’t you make the canisters configurable? What makes it not work? The lack of a standard? Maybe we should ruminate on that and maybe look at what SNS is doing for proposals?

Hey…what is your time line on this. I’d love to see it get wrapped up because I’d live to talk to you about a more permanent opportunity if you are interested. Are you currently working on another project? Where are you located?

Hey! Well I was about to tell you that the implementation of the backend is very closed to being finished, probably will be in one or two days. The test coverage is not perfect but quite good. For now I complied with the initial bounty description only, which means:
(1) I haven’t updated the frontend yet, it’s still readonly, no way to interact with the dao or feed cycles
(2) I haven’t checked how to integrate it with SNS, I need to ramp-up on all the forum discussions on this first

For (1) it will probably take me one or maybe two weeks more. Ultimatly it would be nice to have it work, it would feel like having a real product that every random people could use.
For (2) I have no idea yet, I don’t even know if it will be possible. I actually was hoping to get a part of the bounty reward or so before digging into that.

Right now I’m only working on the bounty and I don’t have any set plan for after, so yes I am definitely interested on working on something more permanent if it involves the IC :slight_smile: I am located in Montreal, Canada.

Hi!

I advanced on the frontend side, it will still probably take a week to be finished. I used the plug and stoic wallet to log the user in.

I have been looking deeper on the SNS integration. It’s very probable I’m missing something, but with what I’ve found it shall be possible to interface with it, but it’s not trivial.

First thing, the frontend. The current architecture:

detailed_architecture_1

Proposal 1.1 If we want to be able to use the SNS governance, one could have a configuration during deployement to tell the frontend to use the basic Governance or the SNS governance interface to submit/vote/list the proposals:

detailed_architecture_2

With this architecture, the difficulty is in the frontend, which has to handle two different kind of governance interfaces and if configured with the SNS governance, do the right transfer calls to make proposal to configure the cycles provider and list/vote proposals specific to the cycles provider only.

Proposal 1.2 If we want the frontend to be agnostic of the type of governance, one could make the current governance configurable and wrap the SNS governance calls.

But this will still require the frontend to call AddNeuronPermission on the SNS governance canister to give the basic governance canister the right to submit/vote the proposals. In some regards, this is similar to what is being done right now with the current governance: to submit a proposal, the frontend first asks the governance canister the transfer parameters for the submission deposit (canister id, transfer arguments (for EXT and LEDGER) or allowance arguments (for DIP20)), then performs the transaction, then only calls submitProposal on the governance canister. Right now it’s done in kindof a switch in the frontend (see CyclesDAO/actors.tsx at main · sardariuss/CyclesDAO · GitHub), but it could probably be done in an IC raw call (or I saw that in plug you can do that in a window.ic.plug.batchTransactions too) so the frontend does not have to handle this switch and stay agnostic of the actual governance implementation.

Second thing, the minting. The current architecture:

detailed_architecture_4

Proposal 2.1 An easy solution would be to just no mint the same tokens:

detailed_architecture_5

And then probably have another service that swaps both tokens in 1:1. This is just an idea that poped in my mind, I don’t know the consequences of this.

Proposal 2.2 Add the ICRC-1 token in the list of token standards supported AND make the MintAccessController expose the ICRC-1 interface fonctions so it is transparent for the SNS Governance:

detailed_architecture_6

The implementation might simply consist of calling the same function on the configured ICRC-1 canister (but the mint that shall check if the caller is in the list of authorized minters). These functions shall probably trap if the configured token is not ICRC-1? One flaw of this design is that the MintAccessController has to be deployed before the SNS Governance, otherwise it’s not possible to make it the owner of the ICRC-1 token.

Propoal 2.3 I haven’t been thinking too much about it, but is it absolutly needed the CyclesProvider mints token? Could it not just transfer tokens ? From what I read from the SNS discussions, it seems like it’s not planned to give to the canisters managed by the SNS (the SNS root dapp canisters) any possibility to mint, but rather have a SNS proposal that mints a bunch of tokens for them. Maybe we could think about an automatic submit proposal that ask to mint tokens to the SNS if it gets below some threshold?

You’ve thought a lot more than I have about this at this point. What do you think is the best solution?

Front end: Let’s keep it simple. The SNS isn’t out yet, so we could just release the governance interface first and add the sns branch later if there is demand.

Minting: I like 2.3, but perhaps we have to have a switch. It is certainly nice to have the cycle dao canister mint if it can, but if not, then it can submit a proposal to sns to mint tokens to it. This seems like a good governance loop. This could be configurable.

Right now 1.2 and 2.3 make the most sense to me. For 2.3. though, it requires small modifications to make the MintAccessController more configurable (configure it to mint or just transfer tokens) and if we want something that submits a proposal automatically to refill the tokens, we will need to assign a dedicated neuron to the CyclesDAO, but it’s a little price to pay.

Sounds good. Thumbs up for minimum characters.

1 Like

Hi!

I finally would like to submit my application for the bounty. There are a few limitations and tasks left (see readme.md and github issues) but the applicaton looks good, seems quite stable and hopefully does the job! Note that this does not include the SNS integration.

As a reminder, the code is here: GitHub - sardariuss/CyclesDAO: Attempt to solve IC-Devs' Bounty #17: A DAO for cycles

If you want a demo I could record a video or do it live.