TOKO/Toolkit/IC Memory

Developer Infrastructure & Upgrade Safety

IC Memory

Validate before you open stable memory.

IC Memory is a stable-memory layout protection framework for Internet Computer canisters. It protects against one of the most dangerous upgrade risks: opening the wrong stable memory after deployment and silently corrupting state.

RustStable-memory governanceMIT / Apache-2.0Extracted from Canic

The problem

A bug that compiles, installs, and corrupts

On the Internet Computer, stable memory is addressed by numeric MemoryManager IDs. If an upgrade accidentally swaps which logical store maps to which physical slot, the canister can open orders data as users data — and vice versa. It still compiles. It can even install. Then it quietly corrupts state.

IC Memory remembers the mapping forever and validates it on every upgrade, rejecting incompatible layouts before any stable-memory handle is opened.

the bug
// v1 ships with
app.users.v1  -> MemoryManager 100
app.orders.v1 -> MemoryManager 101

// a later upgrade accidentally swaps them
app.users.v1  -> MemoryManager 101
app.orders.v1 -> MemoryManager 100

// IC Memory rejects this BEFORE memory opens

How it works

Declare, register, bootstrap, then open

01

Permanent mappings

Records the binding between each logical store and its physical stable-memory slot, and treats that mapping as permanent.

02

Validation on upgrade

Rejects any attempt to move a store to a different slot, reuse a slot, or introduce incompatible layout changes.

03

Multi-crate composition

Every crate registers into the same linked runtime. Bootstrap validates the complete layout from all crates at once.

04

Stable keys

Permanent logical names like namespace.component.store.vN describe ownership and purpose, not the current memory ID.

Where it shines

Most valuable for multi-store canisters, generated canister frameworks, plugin architectures, and long-lived systems whose storage evolves across releases. A tiny canister with one fixed stable structure probably doesn't need it.

Quick start

Bootstrap once, then touch stable data

Declare the MemoryManager IDs your crate owns, open stable structures through ic_memory_key!, and bootstrap before any stable data is touched — in both init and post_upgrade.

rust
// declare the IDs this crate owns
ic_memory::ic_memory_range!(start = 120, end = 129);

// validate layout before opening stable memory
#[ic_cdk::post_upgrade]
fn post_upgrade() {
    ic_memory::bootstrap_default_memory_manager()
        .expect("valid stable-memory layout");
}

Evolve your canisters safely

Read the safety invariants, advanced guide, and protocol whitepaper on GitHub.