sauce verify runs the same checks on a payload, a cook’s calldata or a transaction from the command line.
The settle programs
On EVM,
main(tokens, minOut, recipient) takes its three values as run-time arguments, so one compiled program of SETTLE_WIRE.PROGRAM_BYTES (410) bytes serves every token list, floor and recipient. Before any transfer it requires the Pot’s balance of tokens[0] to be at least minOut (0 turns the floor off), then sweeps the Pot’s whole current balance of every listed token to recipient. Each transfer has OpenZeppelin SafeERC20 semantics: a token that returns nothing is swept, and a false return, a malformed return or an address with no code reverts the sweep.
The floor reads the Pot’s current balance, so a balance that was already there, or that someone donated, counts toward it and is swept with the rest. The floor says what the Pot holds, not what an earlier swap produced.
On Solana the floor and the split between the two token-program slots are compiled into the program, and each escrow is an attached account: 3N + 3 accounts for N escrows.
validateSettleProgram
Checks that an EVM payload is the pinned settle program followed by a canonical argument tail, and decodes the tail.Import
Usage
ver-validate.mts
Signature
Parameters
payload: the settle program’s bytes followed by its ABI-v1 arguments: theprogramargument ofPot.cook(engine, program).accepted: the program hashes or{ hash, bytes }pins to accept. Default: the current pin,SETTLE_WIRE.PROGRAM_HASHatSETTLE_WIRE.PROGRAM_BYTESbytes. An explicit list replaces the default, and an empty list accepts nothing.
Returns
DecodedSettleProgram: the tokens in source order (tokens[0] is also floorToken), minOut, recipient, the program bytes and their keccak256, and the argument tail. Addresses are lower-case hex.
Throws
SettleDecodeError, whose code is one of EMPTY, PROGRAM_TRUNCATED, ARGS_TRUNCATED, ARGS_OVERLONG, TOKENS_OFFSET, TOKENS_EMPTY, DIRTY_ADDRESS_WORD, ZERO_RECIPIENT and PROGRAM_HASH. The tail must be canonical: the canonical token-array offset, a non-empty token list, a non-zero recipient, clean address words and no trailing bytes. Some other encodings run on the engine but are refused here, so a payload that validates has one byte representation of its values.
The pin is the hash of the settle program with ABI-v1 arguments, the only argument encoding. A payload whose arguments use any other encoding is not accepted.
Inspection levels
Only the hash check establishes that the bytes are the settle program; a structural decode accepts any bytes of the right length.
SETTLE_VECTORS and SETTLE_REJECTIONS are the conformance payloads, valid and refused, for a decoder written in another language.
decodeSettleCall
UnwrapsPot.cook(engine, program) calldata and validates the program it carries.
Import
Usage
ver-cook.mts
Signature
Returns
decodeSettleCall: the decoded settle withengine, the engine the cook names (lower-case), ornullwhen the calldata is not a cook or its program is not the settle program. It never throws for those. It readsPot.cookcalldata only: a signed cook (cookSigned) returnsnull.extractEvmSettleFromCalls: the first call in the batch that carries the settle, with itscallIndexandtarget, ornull.
engine with the engines you trust, without regard to case: the settle program on an engine someone else chose is that engine’s computation. Compare target with your Pot: matching is by selector and program bytes only, so a contract that exposes the same cook selector and ignores the payload would match. extractEvmSettleFromCalls reports the first settle it finds and examines no other call, every one of which executes: check the call count and each call’s position yourself. The decoder also reads the SauceRouter.cook(bytes[]) form, where only the first ingredient is examined and engine is absent; check ingredientCount there.
Pins and reproduction
SETTLE_WIRE holds the current pin. A settle program with another hash or length is accepted only when you pass its pin explicitly.
Usage
ver-reproduce.mts
Signature
validateSettleProgram accepts a program with another hash or length only when you pass its { hash, bytes } pin explicitly, beside the current one. Pass the full record: a bare hash is read at the current length, so it cannot match a program of another length. Import the SDK’s pins rather than copying their values. sauce verify --pin <hash:bytes> adds a pin on the command line. The verifier itself neither loads the source nor recompiles it.
verifySvmSettleProgram
Recompiles the Solana settle program with the floor and split you expect and compares the bytes, and checks the manifest’s account names.Import
Usage
ver-svm.mts
Signature
Parameters
bytecode,manifest: the program and its account manifest.expected.minOut: the floor on escrow 0;0nfor none.expected.splCount: how many escrows sweep through the first token-program slot; the rest use the second.
Returns
genuine is true when the bytecode equals the recompiled svmSettleSource(N) for those values and the manifest’s slot names equal svmSettleRefs(N). escrowCount is inferred from the 3N + 3 account shape. A non-genuine result carries mismatch and never throws. It says nothing about the addresses attached to a real instruction.
verifySvmSettleExecution
Decodes a raw engine instruction, resolves its accounts against the settle references by position, and checks the program it runs.Signature
verifySvmSettleProgram example calls it on an inline and a staged instruction.
Parameters
instructionData: the raw engine instruction’s data. A Kitchencookorcook_from_accountinstruction has another layout and must not be passed here.accounts: the instruction’s full account list, as addresses or{ address, ref }.wireFormat:"gated-v1"by default, the released engine’s instructions as the Kitchen sends them.minOut,splCount: the values you expect, as forverifySvmSettleProgram.bytecode: for a staged execution, the staged bytes you read yourself from the code account the instruction names.pin: for a staged execution, a SHA-256 of the staged bytes from your own evidence, normally the matching Kitchencook_from_accountinstruction.
Wire formats
With"gated-v1", the decoder reads:
It removes the code account and the trailing Pot, resolves the
3N + 3 settle slots by position, and returns the parsed gate (owner, salt, bump, Pot) and the codeAccount. It refuses a truncated header, extra staged data, an invalid address and an account count that fits no settle. Labels in accounts are diagnostic; positions decide identities.
"legacy-ungated" reads the historical 8-byte header, for inspecting old instructions only; it does not make them executable on the released engine. The two are not interchangeable: given released data, "legacy-ungated" reads the header as program bytes and the result is not genuine, and given legacy data, the default "gated-v1" throws on the account count.
Returns
Checkgenuine and verifiedBy together:
execute_from_account carries no content pin. A bytecode or caller-asserted-pin result is as good as your evidence connecting that pin to the code account the instruction runs; the helper fetches nothing. Canonical bytes supplied without a pin cannot authenticate a staged execution.
Throws
decodeSvmSettleExecution and verifySvmSettleExecution throw for data or an account list they cannot decode in the chosen wire format.
What a genuine result proves
A genuine result proves the program’s identity: the bytes that run are the settle program the package ships, with the parameters reported, under the pin evidence you supplied for a staged program. It does not prove:- that the engine or the call’s target is one you trust: on EVM compare
engineandtarget; on Solana check the engine program id againstv12SvmEngineProgramId()(Deployments); - that the gate is valid: the parsed owner, salt, bump and Pot are not checked as a Pot derivation or a signature;
- the roles, owners, mints or destinations of the attached accounts;
- that the Kitchen’s own instruction around the engine call is sound, or that any other instruction or call in the transaction is;
- that the transaction succeeded, or what it moved. For a transaction that has already run, read its result.
Next steps
sauce verify: the same checks from the command line.- Cook: what
Pot.cook(engine, program)runs. - Security considerations: what Sauce checks and what it leaves to you.
- Deployments: the engines and Kitchens the SDK pins.
