Canister controller and cycle balance need to be public

If we’re interacting with a service, we should know how much runway it has left. If it’s a NFT canister that only has 1T left, I wouldn’t be comfortable storing long term assets in it.

Also, why should it be private?


If privacy is the concern, than at least give developers the ability to make cycle balance/controller available publicly.

I agree re: neurons too - cached stake not being available to non-controllers doesn’t seem smart as we can calculate manually as per @wang’s msg OR we can just lookup the neuron account and see the balance in the ledger.

Followees may be a privacy thing I guess, but at least allow users to specify if they can make this publicly available too.

I would prefer default public, optional private. Then, it’s up to developers to explain to their users why things are private.


Yup agree with that too

If you want to feel comfortable storing an nft, the cycles balance isn’t enough you’d have to have the source code to make sure the cycles couldn’t be transferred out to someone and also you’d need to make sure that the contract can only be changed by a sufficient decentralized vote , or you’d have a set up where you spin up and fund your own nft canister once the standards come . So for those cases where the source is known to you there can be a public canister function that gives the current cycles balance and you can certify that it is , but the ic is not just a platform for open tokenized dapps, it’s the global-computer that’s meant to host the every kind of the software, not every business wants the world to know how much money they are making. wallets, cycles will be a stable coin, I want to keep my money-count with my self. the blockchain itself certifies the global cycles count if you are thinking bout that.

I do think there should be a way for a canister-controller to let non-controllers certify the canister-source with the hash and certify the controller but i think there might already be a way to do that with the legations.

Edit: controller and module_hash are public, see below.

Agreed that cycle balance is just one of the many requirements for asset storage.

Using native cycles as a medium of exchange/unit of account is cumbersome, so I imagine wrapped cycles will fill that role. Whether these wrapped tokens have privacy features or not is a separate concern.

the ic is meant for personal code systems as well. using native cycles as a medium of the change is the most straight-forward way to do it. there will be standards that catch on that let people send and get cycles from personal canisters with custom flows of some sort.

I am testing my self and I see the controllers and the module_hash are public.

  • Ledger canister:
    • module_hash: 8e478353381b52ad3926601fc730982aa8886b78a089ddd6d184c9b5641d2d7a
    • controllers: [[0, 0, 0, 0, 0, 0, 0, 3, 1, 1]] // r7inp-6aaaa-aaaaa-aaabq-cai
  • dscvr: h5aet-waaaa-aaaab-qaamq-cai:
    • module_hash: 2664385b7ad001123d8cea1f7147fad005d012116139787d9054b2f3a62718ec
    • controllers: [[0, 0, 0, 0, 0, 48, 0, 20, 1, 1]] // g6mnv-cyaaa-aaaab-qaaka-cai

Summary of what data is available and how. Everything public off-chain should be public on-chain as well!

Data Public, off-chain Public, on-chain Controller, on-chain
Subnet :white_check_mark: :no_entry_sign: :no_entry_sign:
Controller :white_check_mark: :no_entry_sign: :white_check_mark:
Status :white_check_mark: :no_entry_sign: :white_check_mark:
Module Hash :white_check_mark: :no_entry_sign: :white_check_mark:
Cycle Balance :no_entry_sign: :no_entry_sign: :white_check_mark:
CPU/Mem :no_entry_sign: :no_entry_sign: :white_check_mark:
1 Like

What do you mean that the controller and module hash are only public off-chain? The path: canister/canisterId/controlller in the system state tree which we can call and certify the sponse , gives the controller of a canister. ?

Is the state tree available within a canister? How do I access it with Motoko or Rust?

1 Like

I think there can an easy opt-in solution to make canister status public, without modifying the current IC behavior:

  1. Create a “blackhole” canister, with an exported interface canister_status.
  2. The method just calls ic0.canister_status to lookup status of a given canister id.
  3. If anyone wants to make their canister status public, just add “blackhole” to the controller list.
  4. But that wouldn’t be safe if “blackhole” can be changed. To make it safe, “blackhole” should have its controller field removed (or set to itself).

What do you think? @wang


@wang Check this out GitHub - ninegua/ic-blackhole: Once a canister sets its only controller to a black hole, it becomes immutable and more!

With the blackhole canister, you can check the status of any canister that has set one of their controllers to the blackhole canister. For example to see the status of the blackhole canister itself:

dfx canister --network=ic --no-wallet call blackhole canister_status '(record { canister_id = principal "e3mmv-5qaaa-aaaah-aadma-cai"; })'
  record {
    status = variant { running };
    memory_size = 304_221;
    cycles = 2_126_143_362_964;
    settings = record {
      freezing_threshold = 2_592_000;
      controllers = vec { principal "e3mmv-5qaaa-aaaah-aadma-cai" };
      memory_allocation = 0;
      compute_allocation = 0;
    module_hash = opt blob "!\0c\f9A\e5\caw\da\ac1J\91Qt\83\ac\17\12dR~=\0dq;\92\bb\95#\9d}\e0";

Thanks Paul. There is a need for a dead/unowned principal but having to remember e3mmv-5qaaa-aaaah-aadma-cai isn’t very ideal, I think aaaaa-aa would be better for that usecase.

I’m still in favor of public by default because I don’t think most devs will bother to opt-in, especially if the process for adding multiple controllers is complex.

Perhaps building this into dfx would be better? Add a flag to dfx.json like public_status: true which automatically adds the blackhole controller.


hmmm, i see, i think controller and module_hash should be able to be seen within another canister if it is public from the outside.


I have to disagree with that premise. Making something accessible programmatically has a totally different quality, allows much easier abuse, and cannot be fixed later without breaking existing apps.

That would be terrible, and would negate all lessons learnt from the unfixable privacy violation pandemic on the Web.

I already remarked this elsewhere: if we are at all serious about building Web 3.0, then we must avoid repeating the old Web’s mistakes, and make principles of least authority, data austerity, and explicit consent the guiding principles.


I agree with @rossberg


For people who are willing to make cycle balance public through the black hole canister, you now can enjoy an automatic topup service too!

Please see Worry about your favorate canister running low on cycles? You got it covered!


Canister controllers and module hash is available through dfx using

❯ dfx canister --network ic info ivcos-eqaaa-aaaab-qablq-cai
Controllers: hgfyw-myaaa-aaaab-qaaoa-cai
Module hash: 0x2d8060fe316775976ad0a33975e846e98b649536be51c8bcf33a7c61806041c6

How to achieve same by using JavaScript?

Also, by using nns/lifeline - rno2w-sqaaa-aaaaa-aaacq-cai canister and method canister_status we can get Canister’s controllers information as an error.

any other cleaner approach to get controllers and canister running status, module hash using js/httpAgent?

dfx actually gets the controller and hash of a canister through read_state call. You can also do that using low level API calls using agent-js.

However, only a controller of a canister can get its cycle balance and other info. This means, unless a canister’s controller purposely decides to expose such info to the public, they will remain private information.

One way for a developer to voluntarily expose such data is to use the black hole canister, simplying by adding the black hole canister id as one of the controllers of your own canister. Then others can send an update call canister_status to the black hole canister to get all status info including remaining cycle balance. It is useful and safe because the black hole canister itself is immutable. I also built a TipJar service to help monitor canister cycle balance and top up them when they run low, and of course, only those with blackhole as one of their controllers are supported.