Skip to main content

migrate_chain

Macro migrate_chain 

Source
macro_rules! migrate_chain {
    ($account:expr, $program_id:expr, { $($old:ty => $new:ty : $f:expr),+ $(,)? }) => { ... };
    ($account:expr, $program_id:expr, payer = $payer:expr,
     { $($old:ty => $new:ty : $f:expr),+ $(,)? }) => { ... };
}
Expand description

Typed multi-hop layout migration: probe-and-migrate each declared hop in declaration order, so ONE call heals an account from ANY declared starting version to the newest, the chain Quasar’s pairwise Migration<From, To> cannot express in one instruction.

ⓘ
// In place (every hop's target must already fit the allocation):
let hops = hopper::migrate_chain!(account, ctx.program_id(), {
    VaultV1 => VaultV2: widen,
    VaultV2 => VaultV3: add_flag,
});

// With ONE up-front grow to the largest hop target, rent topped up
// from `payer` (see `ensure_fits_with_rent`):
let hops = hopper::migrate_chain!(account, ctx.program_id(), payer = payer_view, {
    VaultV1 => VaultV2: widen,
    VaultV2 => VaultV3: add_flag,
});

Each hop probes the header for a fully-valid $old identity and, only then, runs migrate_layout (which re-verifies under its own borrow and carries the owner+writable security gate). An account already at a later hop’s source version simply skips the earlier hops; an account matching NO hop is left untouched and the chain returns 0, the caller’s subsequent typed load rejects foreign layouts exactly as before, so the chain is a healing pass, not a validator. Evaluates to the number of hops applied (u32).

The expansion uses ?, so the surrounding function must return Result<_, ProgramError> (or a compatible error).