Deleting a canister vs. Cycle Drain + Black Hole-ing it

Is there a way to set up a canister such that it refuses any cycle top-ups from external parties?

If there is such a way, why should I delete a canister instead of just black hole-ing it?


Let’s say I want to spin down a canister, here are the following steps for:

1. Deleting a Canister

  1. Transfer cycles
  2. Stop canister
  3. Delete canister

Canister is now deleted

2. Cycle Drain + Black Hole-ing a Canister

  1. Transfer cycles (only leave enough cycles to perform step 2)
  2. Black hole canister (remove self and update controller to the black hole canister)

Canister is now black holed and frozen (non-responsive)


Question: If I can just cycle drain and black hole a canister in 2 async steps to effective delete it, what’s the incentive to take 3 async steps to actually delete a canister?

If a canister is cycle drained, it doesnt get immediately deleted. There is a grace period. What if you wanted your canister to get immediately deleted?

1 Like

Right, but if your canister is

  • cycle drained (can’t perform actions or respond to requests)
  • black holed (can’t be accessed or updated),

and has no way of being topped up - isn’t your canister essentially the same as being deleted for all intensive purposes?

Maybe a usecase for deletion is if you wanted to have compassion for the canister and put it out of it’s misery, rather than leaving it in that existential limbo that you describe :smile:

I thought you could provide a refund address when you delete the canister for the left over cycles.

Is there any documentation for this?


I don’t see a delete_canister refund address as part of the API. See the following IC management canister methods from the Interface Spec

deposit_cycles : { canister_id : Principal } -> async ();

Use this with Cycles.add() from the experimental cycles API to transfer cycles to a specific canister before stopping and deleting the canister.


stop_canister : shared { canister_id : Principal } -> async ();
delete_canister : { canister_id : Principal } -> async ();

To stop and delete the canister.
1 Like

Maybe it was a post from someone suggesting it be added.

There’s another reason for not wanting to actually delete your canisters: you can always re-use them, without having to pay 0.1T for each canister_create. I believe unistall_code should make them consume 0 cycles (need confirmation on that), and you’d still be able to re-install using the same private key for a long time (currently ~10 years from what I’ve read).

1 Like

But isn’t all data removed as well? And if so, whats the point of the grace period then?

@icme
As of dfx 0.8.4, cycles are automatically transferred to wallet when running dfx delete canister
Related post

1 Like

Right, this is to the wallet canister, not a user specified canister - so better to use transfer_cycles beforehand if you want control of where your cycles end up.

Curious if anyone can confirm the above, as well about what amount of space an uninstalled canister occupies on a subnet.

Also, one could just leave the code installed but have it reject every message via inspect_message - I wonder how close this would come to 0 cycles in cost

Is this more of a theoretical question, or is there a good reason why you would rather blackhole a useless canister rather than delete it?

Both.

Based on what I’ve outlined above, if I cycle drain + black hole a canister that’s only 2 inter-canister calls vs. 3 inter-canister calls for draining & deleting the canister, meaning one less step where a message could fail to reach the management canister.

i think this is what dfx does for you when you delete a canister from the command line

3 Likes