> ## Documentation Index
> Fetch the complete documentation index at: https://docs.eco.com/llms.txt
> Use this file to discover all available pages before exploring further.

# The V12 engine

> V12 is the engine that runs Sauce bytecode, as a contract on EVM chains and as a program on Solana. Read it to understand what executes your program.

V12 is the Sauce engine, the interpreter that executes the bytecode the Sauce compiler emits. It is deployed as a contract on EVM chains and as a program on Solana. The bytecode is V12's own instruction set: it is not EVM code and not a Solana program, and only a V12 engine runs it.

On an EVM chain you never call the engine: a cook names it, and your Pot runs it. On Solana a cook goes through the Kitchen, which calls the engine, or straight to the engine's own instruction. The [`sauce` command](https://docs.eco.com/sauce-sdk/cli/overview) 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 a `try`/`catch` block 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](https://docs.eco.com/sauce/types.md#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 for `zero = 0`; a write inside `f` happens when execution reaches it.
* What `main` returns is the engine's output. On an EVM chain it is the return data of [`cook()`](https://docs.eco.com/sauce/cook#return-values).

```ts checked.sauce.ts theme={null}
// Returns a - b. Arithmetic is checked: when b > a, the program reverts.
//
//   sauce simulate checked.sauce.ts --chain base --owner <address> --args <a> <b>
//
//   a: Uint256   the number to subtract from
//   b: Uint256   the number to subtract
function main(a: Uint256, b: Uint256): Uint256 {
  return a - b;
}
```

Simulated with `--args 7 5` and with `--args 5 7`, on a local fork of Base at block 52965000 with the current contracts:

```text theme={null}
The cook succeeds from 0x1111…1111: gas used 50656 for the cook, after the Pot's deploy (1. below), returns 0x0000000000000000000000000000000000000000000000000000000000000002
main returns Uint256: 2
```

```text theme={null}
The cook reverts: it reverted with no data (out of gas, or a revert with no reason)
```

The underflow carries no reason string. A `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 of `cook(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](https://docs.eco.com/sauce/pot.md#its-address)). 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:

| | Through the Kitchen (the default) | Directly on the engine |
| - | - | - |
| Instruction | the Kitchen's `cook`, or `cook_from_account` for a staged program | the engine's `cookAndPay`, or `cookAndPayFromAccountPinned` for a staged program |
| Authority the program has | the owner's Pot, which the Kitchen signs for, and the transaction's signers | the transaction's signers only; no Pot |
| Execution fee | charged by the Kitchen before it calls the engine | charged by the engine before the program runs |

Both read the fee from the Kitchen's fee account and pay it into that account. [cook() on Solana](https://docs.eco.com/sauce/cook.md#on-solana) covers the instructions, compute and call depth.

## Instruction set label

The compiler labels each artifact with `isaRevision`. 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, and `V12_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 `sauce` command compiles the file you give it each time.
* Build unsigned transactions with the installed SDK: a cook that `sauce tx` printed names the engine of the release set that built it.
* `sauce pot list` shows the release each recorded Pot was created under.

Every SDK builder that names an engine calls `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):

```json theme={null}
"compiler": { "name": "@eco-incorp/sauce-compiler", "version": "…" },
"engine": { "release": "v12-evm", "version": "…", "commit": "…", "address": "0x0F50…0f67" }
```

For Solana the engine is named by its program id:

```json theme={null}
"engine": { "release": "v12-svm", "version": "…", "commit": "…", "programId": "53eS…2nSW" }
```

## 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](https://docs.eco.com/sauce-sdk/reference/deployments.md) 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:

```bash theme={null}
sauce pot --chain base --owner <address>
```

```text theme={null}
On base: the engine 0x0F50…0f67 is deployed; the Kitchen 0x1984…506b is deployed, its execution fee 3744785386350 wei (0.00000374478538635 ETH); the Pot 0x6c91…D3Fe is NOT deployed.
```

That read was on a local fork of Base at block 52965000 with the current contracts.

### In TypeScript

`@eco-incorp/sauce/deployments` exports the release's identities. It reads no chain.

| Export | Returns |
| - | - |
| `v12EngineAddress()` | the EVM engine's address |
| `v12SvmEngineProgramId()` | the Solana engine's program id |
| `v12KitchenAddress()`, `v12SvmKitchenProgramId()` | the Kitchen on EVM chains, and on Solana |
| `v12KitchenImplementationAddress()` | the EVM Kitchen's implementation, behind its proxy |
| `v12RouterAddress()` | the execution Router, which answers a Pot's swap callbacks ([The Pot's Router](https://docs.eco.com/sauce/pot.md#the-pots-router)) |
| `v12QuoteRouterAddress()` | the quote service, a separate contract that prices swaps |
| `v12PotDerivation()` | the Kitchen, the Pot init-code hash and the formula of a Pot's address |
| `v12DeployedAddresses()` | the release record: every address and program id, the Pot address derivation, and each component's release |
| `v12DeployedVersion()` | the EVM Kitchen's release; `v12DeployedAddresses().releases` has each component's |
| `sdkCompilerVersion()` | the compiler release the SDK compiles with |
| `V12_RELEASE_SETS`, `v12ReleaseSet(compiler?)` | every release set, or the set of one compiler (default: the installed one) |
| `assertEngineRunsCompiler(target, engine, compiler?)` | nothing; throws for an engine that the release sets record only for other compilers |

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()`.

```ts theme={null}
import {
  assertEngineRunsCompiler,
  v12DeployedAddresses,
  v12EngineAddress,
  v12ReleaseSet,
  v12RouterAddress,
  v12SvmEngineProgramId,
} from "@eco-incorp/sauce/deployments";

const set = v12ReleaseSet(); // the installed compiler and the four releases its output runs on
console.log(set.compiler, set["v12-evm"].version, set["v12-svm"].version);

console.log(v12EngineAddress()); // the EVM engine, the same address on every EVM chain
console.log(v12RouterAddress()); // the current execution Router
console.log(v12SvmEngineProgramId()); // the Solana engine's program id
console.log(v12DeployedAddresses().evm.pot.derivation); // how a Pot's address is derived

assertEngineRunsCompiler("evm", v12EngineAddress()); // passes: this engine runs this compiler's output
```

The [package reference](https://docs.eco.com/sauce-sdk/api/overview.md) documents each export.

## Next steps

* [Kitchen](https://docs.eco.com/sauce/kitchen.md): the contract and program that create Pots and charge the fee.
* [Pot](https://docs.eco.com/sauce/pot.md): the account a program runs in.
* [Bytecode](https://docs.eco.com/sauce/bytecode.md): what the compiler emits, and how to check that a cook carries it.
* [cook()](https://docs.eco.com/sauce/cook.md): the call that runs a program.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.