pub fn migrate_layout_resizing<Old, New, F>(
account: &AccountView<'_>,
payer: &AccountView<'_>,
program_id: &Address,
shrink_to_fit: bool,
transform: F,
) -> Result<(), ProgramError>where
Old: LayoutContract + Pod,
New: LayoutContract + Pod,
F: FnOnce(&Old, &mut New) -> 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
- The same const direction guards and the writable+owner gate.
- 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 frompayer(which must then be writable and a signer, a well-funded account needs no payer at all). Growth is capped by Solana’sMAX_PERMITTED_DATA_INCREASE(10,240 bytes per instruction), enforced byresize. - The typed in-place migration (
migrate_layout), which re-verifies theOldidentity under its own borrow. - Shrink last, opt-in (
shrink_to_fit, when the allocation exceedsNew::required_len()after migrating): resize down and refund exactly the freed rent-exemption delta topayer, doubly capped, never more thanminimum_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.