Skip to main content

migrate_layout_resizing

Function migrate_layout_resizing 

Source
pub fn migrate_layout_resizing<Old, New, F>(
    account: &AccountView<'_>,
    payer: &AccountView<'_>,
    program_id: &Address,
    shrink_to_fit: bool,
    transform: F,
) -> Result<(), ProgramError>
Expand description

migrate_layout that resizes the account to fit the new shape, with a payer-funded rent top-up, the one migration capability the in-place form defers to a separate realloc.

§Sequence

  1. The same const direction guards and the writable+owner gate.
  2. Grow first (when the allocation is smaller than New::required_len()): compute the rent-exempt minimum for the grown size from the LIVE rent sysvar, and when the account’s balance falls short, debit exactly the deficit from payer (which must then be writable and a signer, a well-funded account needs no payer at all). Growth is capped by Solana’s MAX_PERMITTED_DATA_INCREASE (10,240 bytes per instruction), enforced by resize.
  3. The typed in-place migration (migrate_layout), which re-verifies the Old identity under its own borrow.
  4. Shrink last, opt-in (shrink_to_fit, when the allocation exceeds New::required_len() after migrating): resize down and refund exactly the freed rent-exemption delta to payer, doubly capped, never more than minimum_balance(old_len) - minimum_balance(new_len), and never taking the account below its new minimum.

§The refund rule (why the cap is the point)

Quasar’s Migration<From, To> normalizes the migrated account’s balance to the new rent minimum and pays the WHOLE difference to the payer (quasar account.rs:117-125), run it on a PDA that holds user deposits and the deposits leave with the payer. Hopper refunds only the rent requirement the shrink actually freed; every other lamport stays where it was.

§The shrink hazard (why it is opt-in)

New::required_len() covers the fixed shape. A layout with a dynamic tail (raw_tail, Seq<T>, TailStr/TailBytes) stores live data PAST that length, shrinking to fit would truncate it. Pass shrink_to_fit = false (the context macro’s default; resize = fit opts in) unless the layout is tail-free.