> ## 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.

# Cook transactions

> Build, from TypeScript, the transaction that runs a compiled program on its owner's Pot.

A cook is one transaction from a Pot's owner to the Pot. It calls `cook(engine, program)`: `engine` is the V12 engine that runs the program, and `program` is the compiled bytecode with the encoded entry arguments appended. Its `value` is the Kitchen's execution fee plus any native coin the program spends.

A Pot's address follows from its owner and a salt, so you can compute it before the Pot exists. The Pot exists once someone has sent the Kitchen's `deployPot(owner, salt)`, which anyone can send once for each owner and salt. The [Pot](https://docs.eco.com/sauce/pot.md) and [cook](https://docs.eco.com/sauce/cook.md) pages explain both contracts.

The functions on this page build transactions and sign nothing. Only the signed-cook checks read a chain, through the client you pass them: `checkSignedCookPot`, `cookNonceUsed`, and `verifySignedCook` for an owner with code. Read the chain through your own client, and sign and send with your own wallet.

## Complete example on Base

This script compiles a payment program for Base, encodes its arguments, predicts the owner's Pot, reads the Kitchen fee and builds the cook. It then simulates the Pot's deployment and the cook together with viem's `simulateCalls`, from the owner, at one block. Nothing is signed or sent.

### Prerequisites

* Node.js 24 or newer, with `@eco-incorp/sauce` and `viem` installed.
* A Base RPC endpoint, passed as the script's first argument. The library has none of its own.
* The release's engine deployed on Base. `sauce pot --chain base --owner <address>` reports whether it is. The script also checks: it refuses to build a cook when the engine, the Router or the Kitchen has no code, or when the Kitchen predicts a different Pot than the SDK.

### The script

```ts cook.ts theme={null}
import { DEFAULT_POT_SALT, kitchenExecutionFee, routes, v12PredictPot } from "@eco-incorp/sauce";
import { v12EngineAddress, v12KitchenAddress, v12RouterAddress } from "@eco-incorp/sauce/deployments";
import { v12KitchenAbi } from "@eco-incorp/sauce/evm/engine";
import { bytesToHex, concatHex, createPublicClient, getAddress, hexToString, http } from "viem";
import { base } from "viem/chains";

// node cook.ts <Base RPC URL> [amount]
const [rpcUrl, amountArg = "1000000"] = process.argv.slice(2); // 1000000 is 1 USDC
if (rpcUrl === undefined) throw new Error("pass a Base RPC URL");
const amount = BigInt(amountArg);

const owner = getAddress("0x1111111111111111111111111111111111111111"); // the Pot's owner
const recipient = getAddress("0x2222222222222222222222222222222222222222");

const source = `
function main(to: Address, amount: Uint256) {
  require(pot.USDC >= amount, "not enough USDC");
  USDC.transfer(to, amount);
}
`;

// 1. Compile for Base, and append main's arguments to the bytecode.
const program = routes.compileSauceProgram("base", source);
const args = routes.encodeEntryArguments(program, [recipient, amount]);
const payload = concatHex([bytesToHex(program.bytecode), bytesToHex(args)]);

// 2. Read Base at one block. The release must be deployed there: the engine and Router have code,
//    and the Kitchen predicts the same Pot as the SDK.
const client = createPublicClient({ chain: base, transport: http(rpcUrl) });
const blockNumber = await client.getBlockNumber();
const engine = getAddress(v12EngineAddress());
const kitchen = getAddress(v12KitchenAddress());
const release = { engine, router: getAddress(v12RouterAddress()), kitchen };
for (const [name, address] of Object.entries(release)) {
  if (!(await client.getCode({ address, blockNumber }))) throw new Error(`the release is not deployed: the ${name} has no code`);
}
const pot = v12PredictPot(owner, DEFAULT_POT_SALT);
const kitchenPot = await client.readContract({
  address: kitchen,
  abi: v12KitchenAbi,
  functionName: "predictPot",
  args: [owner, DEFAULT_POT_SALT],
  blockNumber,
});
if (kitchenPot.toLowerCase() !== pot.toLowerCase()) throw new Error("the Kitchen predicts another Pot");
const potExists = (await client.getCode({ address: pot, blockNumber })) !== undefined;
const feeRead = kitchenExecutionFee();
const { data: feeData } = await client.call({ to: feeRead.to, data: feeRead.data, blockNumber });
if (feeData === undefined) throw new Error("the Kitchen returned no fee");
const fee = feeRead.decode(feeData);

// 3. The transactions: the Pot's deployment when it has no code, then the cook.
const deploy = routes.sauceEvmDeployPotCall({ owner, salt: DEFAULT_POT_SALT });
const cook = routes.buildSauceEvmCall({ pot, engine, program: payload, value: fee });
const calls = [...(potExists ? [] : [deploy]), cook].map(({ to, data, value }) => ({ to, data, value }));

// 4. Simulate them from the owner at that block. Nothing is signed or sent.
const { results } = await client.simulateCalls({ account: owner, blockNumber, calls });
const result = results.at(-1)!;

console.log("block:", blockNumber);
console.log("pot:", pot, potExists ? "(deployed)" : "(not deployed)");
console.log("fee:", fee, "wei");
console.log("cook:", { to: cook.to, value: cook.value, bytes: (cook.data.length - 2) / 2 });
console.log("result:", result.status, "gas", result.gasUsed);
if (result.status === "failure") console.log("reason:", hexToString(result.data));
```

Pay 1 USDC:

```bash theme={null}
node cook.ts <Base RPC URL>
```

```text theme={null}
block: <block>
pot: 0x6c9175d272D49e6C8C139A3FE6BC6fDb422eD3Fe (not deployed)
fee: 3744785386350n wei
cook: {
  to: '0x6c9175d272D49e6C8C139A3FE6BC6fDb422eD3Fe',
  value: 3744785386350n,
  bytes: 388
}
result: failure gas 67810n
reason: not enough USDC
```

The owner's Pot holds no USDC, so the program's `require` stopped the cook and its message came back as the revert data. Pay nothing:

```bash theme={null}
node cook.ts <Base RPC URL> 0
```

```text theme={null}
block: <block>
pot: 0x6c9175d272D49e6C8C139A3FE6BC6fDb422eD3Fe (not deployed)
fee: 3744785386350n wei
cook: {
  to: '0x6c9175d272D49e6C8C139A3FE6BC6fDb422eD3Fe',
  value: 3744785386350n,
  bytes: 388
}
result: success gas 82455n
```

Where the release is not deployed, the script stops before building anything:

```text theme={null}
Error: the release is not deployed: the engine has no code
```

Your block, fee and gas differ. To run the cook, the owner signs and sends `deploy` once, where the Pot has no code, and then `cook`, each as `{ to, data, value }` with any wallet library. Read the fee shortly before building the cook: a fee raised between that read and the cook makes the cook revert.

## routes.buildSauceEvmCall

Builds one `cook(engine, program)` call on a Pot.

### Import

```ts theme={null}
import { routes } from "@eco-incorp/sauce";
```

### Usage

```ts encode-cook.ts theme={null}
import { routes, v12PredictPot } from "@eco-incorp/sauce";
import { v12EngineAddress } from "@eco-incorp/sauce/deployments";
import { v12Pot, v12PotAbi } from "@eco-incorp/sauce/evm/engine";
import { bytesToHex, concatHex, decodeFunctionData, getAddress } from "viem";

const program = routes.compileSauceProgram(
  "base",
  "function main(to: Address, amount: Uint256) {\n  USDC.transfer(to, amount);\n}\n",
);
const args = routes.encodeEntryArguments(program, ["0x2222222222222222222222222222222222222222", 1_000_000n]);
const payload = concatHex([bytesToHex(program.bytecode), bytesToHex(args)]);

const engine = getAddress(v12EngineAddress());
const pot = v12PredictPot(getAddress("0x1111111111111111111111111111111111111111"));

const data = v12Pot.encodeCook(engine, payload);
const call = routes.buildSauceEvmCall({ pot, engine, program: payload, value: 3_744_785_386_350n });

console.log("same calldata:", call.data === data);
console.log("to:", call.to);
console.log("target:", call.target);
console.log("value:", call.value);
const { functionName, args: cookArgs } = decodeFunctionData({ abi: v12PotAbi, data });
console.log(functionName, "carries the payload:", cookArgs?.[1] === payload);
```

```text theme={null}
same calldata: true
to: 0x6c9175d272D49e6C8C139A3FE6BC6fDb422eD3Fe
target: 0x0000000000000000000000006c9175d272d49e6c8c139a3fe6bc6fdb422ed3fe
value: 3744785386350n
cook carries the payload: true
```

### Signature

```ts theme={null}
function buildSauceEvmCall(params: SauceEvmCallParams): SauceEvmCall;

interface SauceEvmCallParams {
  pot: AddressInput;
  engine: AddressInput;
  program: Hex;
  value?: bigint | number | string;
}

interface SauceEvmCall extends CallInput {
  readonly to: Hex;
  readonly data: Hex;
  readonly value: bigint;
}

interface CallInput {
  readonly target: AddressInput;
  readonly data: Hex;
  readonly value?: bigint | number | string;
}
```

### Parameters

| Parameter | Type | Meaning |
| - | - | - |
| `pot` | `AddressInput` | The Pot to cook on. Never defaulted: predict it with `v12PredictPot` |
| `engine` | `AddressInput` | The engine the cook runs on. A Pot holds no engine; each cook names one. Use `v12EngineAddress()` |
| `program` | `Hex` | One program: the bytecode with its encoded entry arguments appended |
| `value` | `bigint \| number \| string` | Optional, default `0`. The Kitchen fee plus native coin the program spends |

### Returns

`SauceEvmCall`, in both shapes a call is used in:

* `{ to, data, value }`, the transaction a wallet sends or `client.call` takes. `to` is the Pot's checksummed address.
* `{ target, data, value }`, a call record. `target` is the same Pot as a 32-byte, lowercase, left-padded address.

`value` is a `bigint`.

### Throws

It throws for an engine that the release sets in `/deployments` record only for compilers other than the one the SDK pins, because that engine cannot run this SDK's programs. More than one compiler version can share an engine and Kitchen, so an engine recorded for the SDK's compiler passes even where another set records it too. The message names the engine the SDK's programs need. An engine no release set names is not refused.

### Several programs

`routes.buildSauceEvmCalls({ pot, engine, cooks, value })` returns one call per program in `cooks`, in order, each carrying `value`. Each call is a separate cook and pays the fee; statements inside one program need one cook.

```ts theme={null}
function buildSauceEvmCalls(params: SauceEvmCallsParams): SauceEvmCall[];

interface SauceEvmCallsParams {
  pot: AddressInput;
  engine: AddressInput;
  cooks: readonly Hex[];
  value?: bigint | number | string;
}
```

## v12Pot.encodeCook

The calldata encoder `buildSauceEvmCall` uses: `cook(engine, program)` as hex. `v12Pot` also carries the Pot's ABI as `v12Pot.abi`; `v12PotAbi` is the same ABI as a separate export.

### Import

```ts theme={null}
import { v12Pot } from "@eco-incorp/sauce/evm/engine";
```

### Usage

`encode-cook.ts` above compares it with `buildSauceEvmCall`:

```ts theme={null}
const data = v12Pot.encodeCook(engine, payload);
```

### Signature

```ts theme={null}
const v12Pot: {
  readonly abi: readonly [/* the Pot's ABI */];
  readonly encodeCook: (engine: Address, program: Hex) => Hex;
};
```

### Parameters

| Parameter | Type | Meaning |
| - | - | - |
| `engine` | `Address` | The engine the cook runs on |
| `program` | `Hex` | The bytecode with its encoded entry arguments appended |

### Returns

`Hex`: the `cook(engine, program)` calldata.

### Throws

The same refusal as `buildSauceEvmCall`, for an engine that the release sets record only for other compilers.

## Signed cooks

A Private Pot runs a cook its owner signed, sent by any account, through the Pot's `cookSigned` ([Signed cooks](https://docs.eco.com/sauce/pot.md#signed-cooks)). The owner signs EIP-712 typed data; the sender sends `cookSigned` with exactly the signed value and pays the gas; the Pot pays the Kitchen's fee from its own balance, up to the signed ceiling. `@eco-incorp/sauce/evm/engine` builds each part, and your wallet signs. [`sauce sign`](https://docs.eco.com/sauce-sdk/cli/sign) builds the same from a terminal.

### Import

```ts theme={null}
import {
  checkSignedCookPot,
  cookNonceMasks,
  cookNonceUsed,
  encodeCookSigned,
  encodeInvalidateNonces,
  randomCookNonce,
  signedCookTypedData,
  verifySignedCook,
} from "@eco-incorp/sauce/evm/engine";
```

### Usage

```ts sign-cook.ts theme={null}
import { kitchenExecutionFee } from "@eco-incorp/sauce";
import { v12EngineAddress } from "@eco-incorp/sauce/deployments";
import {
  checkSignedCookPot,
  cookNonceMasks,
  encodeCookSigned,
  encodeInvalidateNonces,
  randomCookNonce,
  signedCookTypedData,
  verifySignedCook,
  type SignedCookExecution,
} from "@eco-incorp/sauce/evm/engine";
import { getAddress, type Account, type Hex, type PublicClient, type WalletClient } from "viem";

// Signs a cook of `program` (the bytecode with main's arguments appended) on the Pot `pot`, with
// the owner's wallet, for any account to send within ten minutes. Returns the transaction that
// sends it and the one that cancels it.
export async function signCook(client: PublicClient, wallet: WalletClient & { account: Account }, pot: Hex, program: Hex) {
  // Refuses an address with no code, a contract that is not a Pot, a Shared Pot, and a Pot
  // created before signed cooks.
  const check = await checkSignedCookPot(client, pot);
  if (!check.ok) throw new Error(check.reason);

  const feeRead = kitchenExecutionFee();
  const { data: feeData } = await client.call({ to: feeRead.to, data: feeRead.data });
  if (feeData === undefined) throw new Error("the Kitchen returned no fee");

  const cook: SignedCookExecution = {
    chainId: await client.getChainId(),
    pot,
    engine: getAddress(v12EngineAddress()),
    program,
    value: 0n, // what the sender sends; the Pot pays the Kitchen's fee from its own balance
    maxExecutionFee: feeRead.decode(feeData), // the fee now; sign more to allow for a rise
    nonce: randomCookNonce(),
    deadline: (await client.getBlock()).timestamp + 600n, // inclusive
    // submitter left out: anyone may send it
  };

  const signature = await wallet.signTypedData({ account: wallet.account, ...signedCookTypedData(cook) });
  if (!(await verifySignedCook({ ...cook, signature, owner: check.owner }, client))) {
    throw new Error("not the Pot owner's signature");
  }

  const send = encodeCookSigned({ ...cook, signature }); // { to, data, value }, for any account
  const cancel = cookNonceMasks([cook.nonce]).map(({ word, mask }) => ({
    to: pot,
    data: encodeInvalidateNonces(word, mask), // from the owner
  }));
  return { cook, signature, send, cancel };
}
```

On a local fork of Base at block 52991146 with the current contracts, with `program` the payment program of the [complete example](#complete-example-on-base) paying 1 USDC, and a freshly deployed Pot holding 5 USDC and 0.001 ETH:

* before the Pot was deployed, `checkSignedCookPot` returned `{ ok: false, reason: "0xFbfB…43E1 has no code: no Pot is deployed there" }`, and after it, `{ ok: true, owner }`;
* `send` was 676 bytes of `cookSigned` calldata to the Pot, with `value` `0n`. A second account sent it: the cook succeeded with 121110 gas, and the recipient received 1000000 USDC base units;
* `cookNonceUsed(client, pot, cook.nonce)` then returned `true`;
* a second signature's `cancel`, sent by the owner, set its nonce, and its `send` then reverted with `NonceUsed()`.

### Exports

| Export | What it is |
| - | - |
| `SignedCookExecution`, `SignedCookCall` | What the owner signs (`chainId`, `pot`, `engine`, `program`, `value`, `maxExecutionFee`, `nonce`, `deadline`, `submitter`), and that with its `signature` |
| `signedCookTypedData(execution)` | The typed data for viem's `signTypedData`. It checks every field, and refuses an engine that the release sets record only for other compilers |
| `signedCookTypedDataJson(execution)` | The same as `eth_signTypedData_v4` JSON: the domain's type written out, every number a decimal string, for a wallet that is not viem |
| `signedCookDigest(execution)` | The 32-byte hash the signature is over |
| `encodeCookSigned(call)` | `{ to, data, value }`: the Pot's `cookSigned` call, with `value` the signed value |
| `verifySignedCook(call, client?)` | Whether the signature is the owner's, as the Pot checks it: a 65-byte signature with `s` in the lower half, or, given a client and an owner with code (a Safe, an EIP-7702 account), its ERC-1271 `isValidSignature` |
| `checkSignedCookPot(client, pot)` | `{ ok: true, owner }`, or `{ ok: false, reason }` for no code, not a Pot, a Shared Pot, or a Pot created before signed cooks |
| `encodeInvalidateNonces(word, mask)` | `invalidateNonces` calldata, which cancels nonces, for the owner to send to the Pot |
| `randomCookNonce()` | A random 256-bit nonce, so two signatures you hand out do not collide |
| `cookNonceWordBit(nonce)`, `cookNonceAt(word, bit)` | The word and bit a nonce sets, and back |
| `cookNonceMasks(nonces)` | Nonces as the `{ word, mask }` pairs `invalidateNonces` takes, one per word |
| `cookNonceSlot(word)`, `cookNonceUsed(client, pot, nonce)` | The storage slot of a nonce word, and whether a nonce is spent, by a cook or a cancellation |
| `POT_SIGN_DOMAIN`, `COOK_TYPE`, `COOK_TYPES`, `COOK_TYPEHASH`, `COOK_NONCES_LOCATION` | The domain's name and version, the `Cook` type and its hash, and the nonce bitmap's storage location |

`checkSignedCookPot` checks the Pot before you sign. The [`@eco-incorp/sauce` reference](https://docs.eco.com/sauce-sdk/api/evm-engine/pot-and-kitchen) has each signature. [Security considerations](https://docs.eco.com/sauce/security-considerations.md#signed-cooks) covers replay, deadlines, the submitter and the fee ceiling.

## v12PredictPot

Computes a Pot's address from its owner and salt, with no chain read: `CREATE2(kitchen, keccak256(abi.encode(owner, salt)), initCodeHash)`, the init-code hash taken from the pinned release.

### Import

```ts theme={null}
import { v12PredictPot } from "@eco-incorp/sauce";
```

### Usage

```ts pot.ts theme={null}
import { DEFAULT_POT_SALT, potSalt, routes, v12PredictPot } from "@eco-incorp/sauce";
import { v12Kitchen } from "@eco-incorp/sauce/evm/engine";
import { getAddress } from "viem";

const owner = getAddress("0x1111111111111111111111111111111111111111");
const treasury = potSalt("treasury");

console.log("default salt:", DEFAULT_POT_SALT);
console.log("treasury salt:", treasury);
console.log("default Pot:", v12PredictPot(owner));
console.log("treasury Pot:", v12PredictPot(owner, treasury));

const deploy = routes.sauceEvmDeployPotCall({ owner, salt: treasury });
console.log("deploy:", { selector: deploy.data.slice(0, 10), value: deploy.value });
console.log("same as v12Kitchen.encodeDeployPot:", deploy.data === v12Kitchen.encodeDeployPot(owner, treasury));
```

```text theme={null}
default salt: 0x0000000000000000000000000000000000000000000000000000000000000000
treasury salt: 0xcbd818ad4dd6f1ff9338c2bb62480241424dd9a65f9f3284101a01cd099ad8ac
default Pot: 0x6c9175d272D49e6C8C139A3FE6BC6fDb422eD3Fe
treasury Pot: 0x0828c60115616802F1D750E9752f9E0392FCec99
deploy: { selector: '0xff9763ac', value: 0n }
same as v12Kitchen.encodeDeployPot: true
```

### Signature

```ts theme={null}
function v12PredictPot(owner: Hex, salt?: Hex, kitchen?: Hex): Hex;
```

### Parameters

| Parameter | Type | Default | Meaning |
| - | - | - | - |
| `owner` | `Hex` | required | The owner's address. Only the owner can cook on the Pot |
| `salt` | `Hex` | `DEFAULT_POT_SALT` | 32 bytes. An owner has one Pot per salt |
| `kitchen` | `Hex` | the release's Kitchen | The Kitchen the Pot is deployed through |

### Returns

`Hex`: the Pot's address. It is the same on every chain where the Kitchen is deployed at the same address. The address is arithmetic, not proof that a Pot exists: check for code with `client.getCode`, as the complete example does.

A Pot's address is keyed to the Kitchen, the owner and the salt, and the Pot's bytecode is part of it. An engine runs only a Pot that its paired Kitchen created ([Compiler and engine pairing](https://docs.eco.com/sauce/v12.md#compiler-and-engine-pairing)); a balance never moves between Pots on its own.

## DEFAULT\_POT\_SALT and potSalt

`DEFAULT_POT_SALT` is the salt of an owner's default Pot: 32 zero bytes. `potSalt(label)` is the salt of a Pot the owner names `label`: `keccak256` of the label's UTF-8 bytes. The `sauce` command's `--salt treasury` is `potSalt("treasury")`. For an exact salt, pass its 32 bytes to `v12PredictPot` as they are.

### Import

```ts theme={null}
import { DEFAULT_POT_SALT, potSalt } from "@eco-incorp/sauce";
```

### Usage

`pot.ts` above prints both salts and the two Pots they give one owner.

### Signature

```ts theme={null}
const DEFAULT_POT_SALT: Hex;
function potSalt(label: string): Hex;
```

### Throws

`potSalt("")` throws: `potSalt: a label names a Pot, so it cannot be empty — the default Pot's salt is DEFAULT_POT_SALT`.

## routes.sauceEvmDeployPotCall

Builds the Kitchen's `deployPot(owner, salt)` call, the transaction that creates a Pot. Send it before the first cook on a Pot that has no code yet.

### Import

```ts theme={null}
import { routes } from "@eco-incorp/sauce";
```

### Usage

`pot.ts` above builds one and checks it against `v12Kitchen.encodeDeployPot` from `/evm/engine`.

### Signature

```ts theme={null}
function sauceEvmDeployPotCall(params: SauceEvmDeployPotCallParams): SauceEvmCall;

interface SauceEvmDeployPotCallParams {
  owner: AddressInput;
  salt: Hex;
  kitchen?: AddressInput;
}
```

### Parameters

| Parameter | Type | Default | Meaning |
| - | - | - | - |
| `owner` | `AddressInput` | required | The Pot's owner, part of its address |
| `salt` | `Hex` | required | The Pot's salt: `DEFAULT_POT_SALT`, `potSalt(label)` or 32 bytes of your own |
| `kitchen` | `AddressInput` | the release's Kitchen | The Kitchen to deploy through |

### Returns

`SauceEvmCall`: `{ to, target, data, value }` with `to` the Kitchen and `value` `0n`. It reads no chain, so it does not know whether the Kitchen has code where you send it, or whether the Pot already exists.

## kitchenExecutionFee

Builds the read of the Kitchen's `executionFee()` and its decoder. It performs no request: you send it as an `eth_call`. The fee can change on chain, so read it shortly before building a cook.

### Import

```ts theme={null}
import { kitchenExecutionFee } from "@eco-incorp/sauce";
```

### Usage

From the complete example:

```ts theme={null}
const feeRead = kitchenExecutionFee();
const { data: feeData } = await client.call({ to: feeRead.to, data: feeRead.data, blockNumber });
if (feeData === undefined) throw new Error("the Kitchen returned no fee");
const fee = feeRead.decode(feeData);
```

### Signature

```ts theme={null}
function kitchenExecutionFee(kitchen?: Hex): ExecutionFeeCall;

interface ExecutionFeeCall {
  readonly to: Hex;
  readonly data: Hex;
  decode(result: Hex): bigint;
}
```

### Parameters

| Parameter | Type | Default | Meaning |
| - | - | - | - |
| `kitchen` | `Hex` | the release's Kitchen | The Kitchen whose fee to read |

### Returns

`ExecutionFeeCall`: `to` and `data` for the `eth_call`, and `decode`, which turns its result into the fee in the chain's native unit.

## Release addresses

`@eco-incorp/sauce/deployments` returns the addresses of the pinned V12 release: the same on every chain, recorded rather than read from one. The values are on [Deployments](https://docs.eco.com/sauce-sdk/reference/deployments.md). The SDK reads no chain, so check that a chain has code at an address before you rely on it.

```ts theme={null}
import {
  v12EngineAddress,
  v12KitchenAddress,
  v12PotDerivation,
  V12_RELEASE_SETS,
  assertEngineRunsCompiler,
} from "@eco-incorp/sauce/deployments";
```

```ts theme={null}
const v12EngineAddress: () => string;
const v12KitchenAddress: () => string;
const v12KitchenImplementationAddress: () => string;
const v12RouterAddress: () => string;
const v12QuoteRouterAddress: () => string;
const v12PotDerivation: () => V12PotDerivation;
const v12SvmEngineProgramId: () => string;
const v12SvmKitchenProgramId: () => string;
function v12DeployedAddresses(): V12DeployedAddresses;
const V12_RELEASE_SETS: readonly V12ReleaseSet[];
function v12ReleaseSet(compiler?: string): V12ReleaseSet;
const sdkCompilerVersion: () => string;
function assertEngineRunsCompiler(target: "evm" | "svm", engine: string, compiler?: string): void;
```

| Export | Returns |
| - | - |
| `v12EngineAddress()` | The EVM engine the SDK's programs run on, which every cook names |
| `v12KitchenAddress()` | The Kitchen proxy, which deploys Pots and gates every cook |
| `v12KitchenImplementationAddress()` | The Kitchen implementation behind the proxy |
| `v12RouterAddress()` | The execution Router, into which a Pot's fallback delegatecalls. Its address is derived from its code; compare Routers by this address |
| `v12QuoteRouterAddress()` | The quote service, separate from the execution Router |
| `v12PotDerivation()` | The inputs `v12PredictPot` uses: `deployer`, `initCodeHash`, `saltFormula` |
| `v12SvmEngineProgramId()`, `v12SvmKitchenProgramId()` | The Solana engine and Kitchen program ids |
| `v12DeployedAddresses()` | The whole release record, EVM and Solana |
| `V12_RELEASE_SETS`, `v12ReleaseSet(compiler?)` | One row per compiler version, naming the engine and Kitchen releases its output runs on |
| `sdkCompilerVersion()` | The compiler version the SDK pins |
| `assertEngineRunsCompiler(target, engine, compiler?)` | Throws for an engine that the release sets record only for compilers other than `compiler` (default: the SDK's). `buildSauceEvmCall` and `v12Pot.encodeCook` call it |

## Next steps

* [Entry arguments](https://docs.eco.com/sauce-sdk/typescript/entry-arguments.md): encode the arguments in the payload.
* [Compiling](https://docs.eco.com/sauce-sdk/typescript/compiling.md): compile the program.
* [sauce tx](https://docs.eco.com/sauce-sdk/cli/tx.md) and [sauce simulate](https://docs.eco.com/sauce-sdk/cli/simulate.md): the same transaction and simulation from a terminal.
* [sauce pot](https://docs.eco.com/sauce-sdk/cli/pot.md): a Pot's address, code and Kitchen fee from a terminal.
* [Deployments](https://docs.eco.com/sauce-sdk/reference/deployments.md): the release addresses.
* [Kitchen](https://docs.eco.com/sauce/kitchen.md), [Pot](https://docs.eco.com/sauce/pot.md) and [cook](https://docs.eco.com/sauce/cook.md): the contracts these transactions call.


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