Future of the Cycles Wallet

The Cycles Wallet has been sitting around mostly undisturbed since Genesis. In its current state, we use it as a place to hold cycles, and to enable dfx to use it to make calls to the Management Canister when you want to create a new canister.

At the time we built it, the execution environment only allowed canisters to have a single controller. That led us to use a design where the Cycles Wallet would create a canister and assign itself as the controller. That is why calls to --network ic are passed through the Cycles Wallet. The wallet is the controller, and dfx itself is not.

This isn’t ideal, and it is no longer necessary. The current design adds cognitive load, adding the --no-wallet option to calls, which is not intuitive. Now that multiple controllers are supported, this enables us to make both the wallet and dfx controllers of the new canister. This would probably end up leading to a new minor version of dfx, so I want to run the design by the community before proceeding.

Change #1 - Canister Creation

Canister creation still needs to be executed live canister holding cycles, so setting up a Cycles Wallet in dfx will still be part of the onboarding process.

The Wallet will accept --controllers, specifying a list of controllers from the dfx command line, and by default it will use your dfx principal and its own.

Change #2 - Canister management

All other dfx commands will go directly to the canister, removing the call the ll-forwarding paradigm, and removing --no-wallet options from all the commands that support them

Change #3 - Enhancements

You may not know this, but your Cycles Wallet has a UI! You can check it out at the raw.ic0.app url for your wallet. It is limited in functionality for now, but it shows you your cycles balance, a not terribly accurate list of the canisters you’ve created, and a UI that lets you send cycles and create new canisters. There’s some basic cleanup we can prioritize, but the vision originally was to have it serve as a simple dashboard for your canisters, allowing you to check their balance, top them up with cycles, and so on. That’s still the direction we would like to take that feature.

That’s the gist! Is this a good direction for the Cycles Wallet? Is the Wallet still necessary, or should all of this functionality get rolled into the NNS dapp? Let me know what you think!



I always use NNS to create canisters, so for my personal scenario, I don’t think it’s needed. Every time I have to add --no-wallet option in command for execution. it will be good to remove it.

1 Like

when create a new canister, controller must be cycles wallet. but i always want the pricipal-id to be the controller, so i need to change the controller pass a command. and i need to use --no-wallet when i upgrade or reinstall the canister, but i always forgot…

so i recommond the principal-id be the controller after create new canister, and remove the --no-wallet options.

1 Like

and I found that when the cycles balance of canister is very small, the cycles can not be recharged through the cycle-wallet, only through command (top up) use icp.
the error show that maybe update call need comsume some cycles(2000590000). but the cycles balance minus the freezing threshold cycles not more than that, Is it possible to do some optimization here?

1 Like

+1 very worth it, if only to save new devs from candid encoding a forwarded wallet call. Excited for this! Sidenote: how would I add another controller to one of my canisters today?

1 Like

The cycle wallet was one of the more confusing parts of the walkthrough when I first started developing on the IC, so the less of it that’s required the better IMO.

As an aside, I still don’t quite understand where cycles are “stored”. AFAIU there’s no cycles ledger canister (excluding WTC) like there is for ICP, and therefore I’ve heard that a canister’s cycles are stored as internal metadata inside the IC system itself (i.e. the replica).

If cycles were instead stored in a ledger, then I suppose wallet canisters wouldn’t be needed in the first place? If so, I’m curious why it wasn’t designed like that to begin with.


According to the Internet Computer Interface Specification, Cycle balance is part of the canister meta data. So it is stored together with canister state, on the subnet that hosts the canister.

First of all, it was designed to be owned only by canisters, not by users. Canister has a “home subnet”, but users do not.

You could also view the cycle balances in all canisters forming a “distributed ledger”, but you really shouldn’t, because the system was not designed to track the movement of cycles and keeping a log of all history. There is nothing that allows you to say “Here is a proof that canister A transferred X amount of cycles to canister B at time T”, at least not directly.

IMHO, this design reflects more truthfully the nature of distributed computing, i.e., the transfer of an asset between point A and point B has nothing to do with anything else. Without central party called “the ledger” to report to, it is more scalable when the number of subnets and canisters grows.

The downside of course is that the security property of “cycles are not minted out of thin air” now depends on all subnets being secure. So there has always been concerns. What happens when a subnet is compromised? Can we contain the damage? Will such precautionary measures create inconvenience for users? Can we really make sure no subnet is compromised ever?

You can clearly see the trade-offs in the design of these two tokens, cycle & ICP. Personally I like to think cycle is more fundamental to the network, and ICP is more of an application. But that is just me.


Again I’d call out attention to Cycles Common Initiative. The community should work together to remove the limitations imposed on cycles, namely:

  1. Being able to send cycles freely between “application subnet” and “verified application subnet”;
  2. There should be no limit on how many cycles a canister can hold.

We developers are handcuffed at the moment, and we should promote more freedom as the better default!


Great analysis.

The downside of course is that the security property of “cycles are not minted out of thin air” now depends on all subnets being secure.

Just to clarify, do you mean that because cycles are owned by canisters in their respective subnets, if any subnet were compromised then its canisters could manipulate their own cycle balances, whose effects would then leak to other subnets?

But because ICP is owned by users and tracked in a single ledger canister on a single NNS subnet, only if the NNS subnet is compromised then ICP could be manipulated?

If so, that makes a lot of sense.

As an aside, it’s kind of interesting that a “central party” ICP ledger canister (which is centralized in concept but decentralized in software) can actually gain both the benefits of centralization (easier to harden one point than many) and decentralization (not easily corruptible).


Update here - changes to the cycles wallet are coming in dfx 0.8.5.

  • Going forward, canisters created through dfx create will have both the dfx default principal and the cycles wallet listed as controllers.
  • All other commands that interact with canisters will use the dfx default identity, instead of being forwarded through the wallet
  • --no-wallet flags are no longer used. That behavior is now default, and --wallet is instead offered to opt into forwarding calls for backward compatibility with existing canisters
  • dfx canister update_settings --add_controller is now added to migrate existing canisters with a cycles wallet as the sole controller