sauce command and the SDK name the released engine in every cook they build.
How a program executes
- The engine runs the program’s steps in order, inside the transaction that carries it: the cook on an EVM chain, the cook instruction on Solana.
- Every contract call the program makes is a call inside that transaction. On an EVM chain it comes from the Pot.
- An uncaught failure reverts the whole transaction: a failed
require, a call that fails, an arithmetic error. On EVM chains atry/catchblock rolls back its own calls, writes and assignments and runs its handler instead; work before the block remains. Solana has no catch. - Arithmetic on numbers is checked. Overflow, underflow and division by zero revert as the program runs; with constant operands they are compile errors. The exception is a call-free array literal indexed at a literal position, where only the element taken is evaluated (Arrays).
- With a helper call, a contract call or a token read (
pot.USDC,USDC.balanceOf(pot)) in an array literal, that call and the elements ahead of it run.[1 / zero, f()][1]and[f(1 / zero), 7][1]revert forzero = 0; a write insidefhappens when execution reaches it. - What
mainreturns is the engine’s output. On an EVM chain it is the return data ofcook().
checked.sauce.ts
--args 7 5 and with --args 5 7, on a local fork of Base at block 52965000 with the current contracts:
require(condition, "message") before the subtraction gives the revert a message.
Where the engine runs
On EVM chains
The engine runs only inside a Pot that its Kitchen created, with the Pot code the engine was built for. The release records both anchors: the Kitchen’s address and the Pot init-code hash. Called directly, the engine refuses. A cook on a Pot is the only way to run a program on an EVM chain. A Pot holds no engine. Each cook names the engine it runs on, as the first argument ofcook(engine, program). While the cook runs, the Pot’s inFlightEngine() returns that engine; outside a cook it returns the zero address.
A Pot’s address follows from the Kitchen, the owner and the salt, so a Kitchen whose Pot code differs gives every owner different Pot addresses. An engine runs only the Pots of the Kitchen it is paired with and refuses any other (Pot). A compiler-only release that keeps the Kitchen keeps every Pot address.
On Solana
Two entry points run the same bytecode with the same account indices:
Both read the fee from the Kitchen’s fee account and pay it into that account. cook() on Solana covers the instructions, compute and call depth.
Instruction set label
The compiler labels each artifact withisaRevision. In the compiler’s typings the only value is "stack-v3", an opaque label.
The label is not a compatibility check. Two engine releases can report the same label while only one of them runs a given compiler’s output, and the compiler does not read a chain to find what is deployed there.
Compiler and engine pairing
Each SDK pins an approved compiler, engine and Kitchen release set. A compiler’s programs run only on the engine releases recorded for that compiler: a new compiler release can emit different bytecode for the same source, which an engine not recorded for it can misread, and an older compiler’s programs can fail on a newer engine. More than one compiler version can share the same engine and Pot family: two release sets can name the same engines and Kitchens, andV12_RELEASE_SETS lists them. Use the installed SDK’s release set rather than assuming that every compiler upgrade changes the engine or Pot address.
The SDK pins one compiler. For each compiler release it records a release set: the EVM engine, the EVM Kitchen, the Solana engine and the Solana Kitchen that the compiler’s output runs on, the digest of each released asset, and each engine’s address or program id. The engines the SDK names and the engine artifacts it ships are those of the installed compiler’s set.
When you send a cook:
- Compile with the version that sends the cook. Bytecode from another compiler runs only on the engines its own release set records. The
saucecommand compiles the file you give it each time. - Build unsigned transactions with the installed SDK: a cook that
sauce txprinted names the engine of the release set that built it. sauce pot listshows the release each recorded Pot was created under.
assertEngineRunsCompiler(target, engine) first: v12Pot.encodeCook on EVM chains, and on Solana the Kitchen’s cook instructions and the engine’s own. It throws for an engine that the release sets record only for other compilers, and its message names the engine the installed compiler’s output needs. An engine that no release set records, such as one you deployed yourself, passes: the SDK has nothing to check it against.
sauce compile --json names the compiler that produced the program and the engine release that runs it (abridged):
Addresses
The engine has the same address on every EVM chain it is deployed on, and the same program id on every Solana cluster. Deployments lists them. A recorded address is not proof that code is there.sauce pot reads whether the engine and the Kitchen are deployed on a chain:
In TypeScript
@eco-incorp/sauce/deployments exports the release’s identities. It reads no chain.
The execution Router is content-addressed: its address follows from its code, so a Router with other code has another address. Compare Routers by address with
v12RouterAddress().
