TL;DR
Minting cycles from ICP to create or top up canisters can currently be done via two distinct flows:
- Legacy Flow:
transfer
→ledger_notify
- New Flow:
transfer
→cmc_notify
The new flow (cmc_notify
) offers superior security guarantees, greater flexibility, and eliminates a critical coupling between the ICP Ledger and subnet operations. This post announces our plan to deprecate and eventually disable the legacy ledger_notify
flow.
Who Should Be Concerned?
If you are using the notify()
endpoint on the ICP Ledger, this post is relevant to you. If you are not aware of this functionality, you most likely do not need to take any action.
Legacy Flow: ledger_notify
(To Be Deprecated)
How It Works
- Transfer:
- Use either the legacy
send()
method or theicrc1_transfer()
method to transfer tokens to a specific subaccount of the Cycles Minting Canister (CMC). - The subaccount encodes a principal:
- If creating a new canister, this is the principal of the intended controller.
- If topping up an existing canister, this is the principal of the target canister.
- The transaction memo specifies whether the transfer is for canister creation or top-up.
- The transaction is recorded in the ledger at block index
idx
.
- Ledger Notify: The user (or anyone) calls
notify()
on the Ledger, passing the transaction indexidx
.
- The Ledger performs checks and then forwards the transaction details to the CMC.
- CMC Processing: The CMC verifies the memo and the intended action. If valid, it mints cycles at the ICP/XDR exchange rate and executes the requested operation.
- Result Propagation: The CMC returns the result to the Ledger, which then relays it back to the
notify()
caller.
Problems with ledger_notify
Flow
- Ledger Coupling to Downstream Canister Calls: The Ledger must wait for responses from the CMC (and potentially other subnetworks). If a subnet stalls, this leaves open call contexts on the Ledger, blocking safe upgrades.
- Limited Deduplication Window: To prevent double spending, the Ledger maintains a record of past
notify()
calls for only 24 hours. If a transaction is not successfully notified within this window, it cannot be used later, effectively causing the loss of those tokens unless manually recovered. - Lost Responses are Unrecoverable: Since the result of
notify()
is returned via the Ledger, losing this response due to frontend failures or network issues means there is no way to recover the canister ID or cycle top-up result. The Ledger does not store the outcome persistently, making it impossible to retrieve the lost data.
New Flow: cmc_notify
(The Superior Alternative)
How It Works
- Transfer: The user transfers ICP tokens to a specific subaccount of the CMC, as above.
- CMC Notify: The user directly notifies the CMC, specifying the transaction index
idx
via one of two distinct endpoints:notify_create_canister()
(for canister creation)notify_topup_canister()
(for canister top-up)
- The notification explicitly includes additional details, such as the intended controller or canister settings for canister creation or the principal of the canister to be topped up.
- CMC Processing:
- The CMC fetches the transaction from the Ledger.
- Ensures that the memo is valid and that the notifier is the transaction initiator.
- Mints cycles and executes the requested operation.
- Result Propagation: The CMC returns the result directly to the caller without involving the Ledger.
Advantages of cmc_notify Flow
- Eliminates Ledger Coupling: The ICP Ledger is no longer involved in downstream calls, making ledger upgrades safer and more flexible.
- Better Deduplication Handling:
- The CMC itself tracks which transactions have already been processed.
- It retains records for 1 million transactions, significantly improving over the previous 24-hour limit.
- If a notification is lost, the result can be recovered by simply retrying the notify call.
- Recoverable Results: The CMC tracks past transactions and their results, so if a response is lost due to frontend connectivity issues, a user can simply reissue cmc_notify call with the same transaction index to retrieve the original result.
- Enhanced Canister Creation Flexibility:
- Users can specify the subnet type or even a specific subnet for canister creation.
- Supports defining initial canister settings at creation time.
How to Migrate
To transition from the legacy ledger_notify
flow to the new cmc_notify
flow, simply replace the Ledger notify()
call with one of the following end points on the CMC:
notify_create_canister()
(for canister creation)notify_topup_canister()
(for canister top-up)
Next Steps & Action Required
We encourage developers to migrate their integrations as soon as possible. A formal deprecation schedule will be announced, after which the legacy ledger_notify
flow will be disabled.
Action Required:
If you are using the ledger_notify
flow, please comment below or reach out to us with the following details:
- Confirmation that you are currently using
ledger_notify
- Your estimated timeline for transitioning to
cmc_notify
- Any blockers or concerns regarding the migration
This will help us ensure a smooth transition for all affected users. For questions or assistance, feel free to engage in the discussion below!