Steps and registers

How a step captures a value and how a later step pipes it back in.

A plan is a list of steps. Two mechanisms move data between them: a step can captureits callee's return value into a register, and a later step can splice a register back into its own instruction data before it runs. That is the entire piping model.

Capture

Set captureInto: non a step. After its CPI returns, PTBVM reads the callee's return data as a little-endian u64 and stores it in register n. Set capturePubkey: true instead to capture a 32-byte pubkey the callee returned, so a later step can reference it as an account.

Splice

Add a dataSplices entry to a step. Before the step runs, PTBVM overwrites width bytes of its instruction data at offset with the value in register. The default width is 8 (a u64). This is how a captured amount becomes the input to the next call.

FieldTypeNote
captureIntonumber | nullStore this step's u64 return value in the given register slot.
capturePubkeybooleanCapture a returned 32-byte pubkey instead of a u64 value.
dataSplices[]{ offset, register, width }Overwrite width bytes of this step's data at offset with a register value. width defaults to 8.

Register file

The register file is a fixed-size array of eight u64 slots, held in a PDA owned by the caller. It lives on chain for the duration of the plan; captured values never round-trip through your client. Slots default to zero.

you type 100swap(100)→ produces 150captureregister file · 8 slots1500000000reg 0splicedeposit(150)amount ← reg 0The client nevertypes 150.Only reg 0 iswritten here.
Register piping. You type 100. The swap runs on chain and produces 150; the VM captures 150 into register 0, then splices register 0 into the deposit's amount before it runs, so the deposit receives 150 without the client ever typing it.

In this section

  • The obligation gate: The hot-potato check that reverts the whole plan if an obligation is left open.
  • Token-2022: Why Token-2022 composes as a plan step with no special casing.