> ## 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()

> `cook()` is the Pot function that runs one program. Read it before you build, sign or send the transaction that calls it.

The EVM Pot exposes this contract function (Solidity declaration):

```solidity theme={null}
function cook(address engine, bytes program) payable returns (bytes);
```

A cook is the transaction that runs one program. On an EVM chain it is a call to the owner's [Pot](https://docs.eco.com/sauce/pot.md):

| Part | Value |
| - | - |
| `to` | the Pot |
| `data` | `cook(engine, program)`: `engine` is the [V12 engine](https://docs.eco.com/sauce/v12.md) the program runs on; `program` is the compiled bytecode followed by `main`'s encoded arguments ([Bytecode](https://docs.eco.com/sauce/bytecode.md#entry-arguments)) |
| `value` | the [Kitchen's fee](https://docs.eco.com/sauce/kitchen.md#the-fee), plus any native coin the program spends |

## Who may call it

A private Pot accepts a direct `cook` call only from its owner. A direct call from another account reverts with `NotOwner()`. A Shared Pot, which has no owner, accepts a cook from anyone.

A Pot created by the current Kitchen has a second entry point, `cookSigned`: the owner signs a cook as EIP-712 typed data, and any account submits it and pays the gas ([Signed cooks](https://docs.eco.com/sauce/pot.md#signed-cooks)).

The `sauce` command builds the cook for the owner: `sauce simulate` runs it without a key, `sauce run` signs and sends it with the owner's wallet, and `sauce tx` prints it unsigned for another signer. [`sauce sign`](https://docs.eco.com/sauce-sdk/cli/sign) signs a cook for another account to submit with `cookSigned`.

## What the Pot does

1. It checks that the sender is its owner, and reverts with `NotOwner()` otherwise. For `cookSigned` it checks the owner's signature, the nonce, the deadline and the submitter instead ([Signed cooks](https://docs.eco.com/sauce/pot.md#signed-cooks)).
2. It forwards the Kitchen's fee to the Kitchen. For `cook`, the fee comes out of the cook's value: a value below the fee reverts with `FeeNotPaid(uint256 required, uint256 provided)`. For `cookSigned`, it comes out of the Pot's own balance, which includes the value sent, up to the signed `maxExecutionFee`: a fee above the smaller of the two reverts with `FeeNotPaid`.
3. It runs the program on `engine`, inside itself and on its own balances. The program runs as the Pot: `pot` and `ctx.self()` are the Pot, and every call the program makes comes from the Pot.
4. It returns what `main` returns.

A cook runs exactly one program. The Pot keeps no engine between cooks: every cook names one.

```ts pay.sauce.ts theme={null}
// Pays `amount` of the chain's USDC from the Pot to `to`.
//
//   sauce run pay.sauce.ts --chain base --wallet <name> --args <to> <amount>
//
//   to: Address       the recipient
//   amount: Uint256   in USDC's smallest unit (6 decimals): 5000000 is 5 USDC
function main(to: Address, amount: Uint256) {
  require(pot.USDC >= amount, "not enough USDC");
  USDC.transfer(to, amount);
}
```

```bash theme={null}
sauce simulate pay.sauce.ts --chain base --owner <address> --assume-balance USDC:5 --args <to> 5000000
```

```text theme={null}
The cook succeeds from 0x1111…1111: gas used 83291 for the cook, after the Pot's deploy (1. below), returns 0x
What moved, in order:
  [1] wallet 0x1111…1111 -> Pot 0x6c91…D3Fe      0.00000374478538635 ETH  the cook's value
  [2] Pot                -> Kitchen 0x1984…506b  0.00000374478538635 ETH  the Kitchen's fee
  [3] Pot                -> 0x2222…2222          5 USDC
```

That simulation ran on a local fork of Base at block 52965000 with the current contracts (abridged). The owner had no Pot yet, so the simulation deployed it first, for 667,003 gas.

## The unsigned cook

`sauce tx` prints the cook as JSON for any wallet to sign. When the Pot has no code yet it prints a plan, the Pot's deployment first:

```bash theme={null}
sauce tx pay.sauce.ts --chain base --owner <address> --args <to> 5000000
```

```json theme={null}
{
  "chainId": 8453,
  "pot": "0x6c91…D3Fe",
  "transactions": [
    {
      "what": "Kitchen.deployPot(0x1111…1111, 0x0000…0000): deploys the Pot, which has no code yet",
      "deploysPot": "0x6c91…D3Fe",
      "chainId": 8453,
      "to": "0x1984…506b",
      "data": "0xff9763ac…",
      "value": "0x0"
    },
    {
      "what": "cook on Pot 0x6c91…D3Fe",
      "chainId": 8453,
      "to": "0x6c91…D3Fe",
      "data": "0xb38dbf14…",
      "value": "0x367e69a4b6e"
    }
  ]
}
```

That plan was read from a local fork of Base at block 52965000 with the current contracts (abridged; the output also carries `sendCalls`, both transactions as one batch for a wallet that sends batches).

* `data` is `0xb38dbf14`, the selector of `cook(address,bytes)`, followed by the ABI encoding of the engine's address and `program`. Here `program` is 287 bytes: the 223-byte program and two 32-byte arguments.
* `value` is 3,744,785,386,350 wei, the Kitchen's fee read when the cook was built. The program spends no ETH, so nothing is added.
* Once the Pot has code, `sauce tx` prints the cook alone: `chainId`, `to`, `data` and `value`.
* `--format cast` prints each transaction as a `cast send` line instead.

## Atomicity

The program's steps run in order inside the cook. An uncaught failure, such as a failed `require`, a call that reverts or a checked arithmetic error, reverts the whole cook, the Kitchen's fee with it: nothing moves, and the sender pays only the gas used up to the failure. Simulated on a local fork of Base at block 52965000 with the current contracts, with no USDC in the Pot, the same cook gives:

```text theme={null}
The cook reverts: the program threw "not enough USDC"
```

On EVM chains a `try`/`catch` block narrows the rollback: when the block fails, its own calls, writes and assignments roll back, the handler runs, and the cook goes on; work before the block remains. Solana has no catch, so there every failure reverts the cook.

The rollback covers this transaction only. What earlier transactions did stays done: an approval a previous cook gave outlives that cook, and its spender can still use it after a later cook reverts. Approve exactly what the next call spends.

## Return values

What `main` returns is the cook's return data. The ABI declares `returns (bytes)`, but the bytes are the value itself, laid out by the type `main` declares, with no ABI `bytes` wrapper around them:

| `main` returns | The return data |
| - | - |
| `Address`, `Uint256`, `Int256` or `bool` | one 32-byte word; a negative `Int256` in two's complement |
| a record | its fields, one word each |
| an array | its elements, one word each, with no offset or length |
| `bytes` | the bytes themselves |
| nothing | nothing |

An array is therefore not what an ABI decoder reads. To return ABI-encoded data, return `abi.encode(...)` as `bytes`. Solana has no `abi.encode`.

```ts balance.sauce.ts theme={null}
// Returns the Pot's USDC balance, in USDC's smallest unit.
//
//   sauce simulate balance.sauce.ts --chain base --owner <address>
function main(): Uint256 {
  return pot.USDC;
}
```

`sauce simulate` decodes the return data as the declared type. With 5 USDC assumed in the Pot, on a local fork of Base at block 53122782 with the current contracts:

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

## Gas

On an EVM chain the wallet that sends the cook pays its gas in the chain's native coin. A cook's gas is the transaction's, the Pot's and the Kitchen's, plus the program's own, which the engine runs step by step. Measured through the released engine and a Pot the Kitchen made, on a local chain:

| What | Gas, about |
| - | - |
| A cook whose program does almost nothing | 43,000, the transaction's 21,000 included |
| One loop iteration that adds two numbers | 1,000 |
| Writing an array element, or reading one | 500, or 300, on top |
| A call to a contract the transaction already called | 2,000 on top, plus what that contract spends |
| The first call to a contract in the transaction | 2,600 more than a later one |
| `crypto.keccak256(abi.encode(a, b))` | 2,000 |

The programs on these pages, simulated on a local fork of Base at block 52965000 with the current contracts:

| Program | Gas used by the cook |
| - | - |
| `checked.sauce.ts` ([V12](https://docs.eco.com/sauce/v12.md)), `a - b` | 50,656 |
| `balance.sauce.ts`, one balance read | 62,950 |
| `pay.sauce.ts`, a balance check and a transfer | 83,291 |
| `supply.sauce.ts` ([Pot](https://docs.eco.com/sauce/pot.md)), an approval and an Aave supply | 218,145 |

* The figure for your program is the simulation's, on the chain as it is when you run it. A swap that crosses more of a pool's price range than it did in the simulation spends more, so leave room between the simulated gas and the gas limit.
* On Base and other OP Stack chains each transaction also pays a fee for publishing its data to Ethereum. `sauce run` counts it in what a run cost.
* A cook that fails pays the gas it used up to the failure, and no Kitchen fee.

## On Arc

Arc's native coin is USDC, so a cook's value, the Kitchen's fee within it, and its gas are paid in USDC. As native value USDC has 18 decimals; it is the same balance as the 6-decimal `USDC` token. Simulated on a local fork of Arc at block 27376858 with the current contracts, `checked.sauce.ts` with `--args 7 5`:

```text theme={null}
The cook succeeds from 0x1111…1111: gas used 50656 for the cook, after the Pot's deploy (1. below), returns 0x0000000000000000000000000000000000000000000000000000000000000002
What moved, in order:
  [1] wallet 0x1111…1111 -> Pot 0x6c91…D3Fe      0.01 USDC  the cook's value
  [2] Pot                -> Kitchen 0x1984…506b  0.01 USDC  the Kitchen's fee
```

Arc includes a transaction only with a `maxFeePerGas` (or `gasPrice`) of at least 20 gwei, its minimum base fee.

## On Solana

A cook on Solana is an instruction, and there are two ways to send one:

| | Through the Kitchen (the default) | Directly on the engine (`--via engine`) |
| - | - | - |
| Instruction | the Kitchen's `cook`, with the program in the instruction, or `cook_from_account` for a staged program | the engine's `cookAndPay`, or `cookAndPayFromAccountPinned` for a staged program |
| Signed by | the owner; the Kitchen then signs for the Pot | the transaction's signers, such as the wallet; nothing signs for a Pot |
| Fee | charged by the Kitchen before it calls the engine | charged by the engine before the program runs |
| Call depth left for the program | three levels of cross-program invocation on mainnet; seven where SIMD-0268 is active | four on mainnet; eight where SIMD-0268 is active |

Both carry a signed `max_execution_fee`, and a fee above it refuses the cook before anything runs. The same compiled program runs either way, with the same account indices.

* **Compute.** A transaction has a budget of 1,400,000 compute units, shared by the engine and every program it calls. A cook that runs out fails whole. `pay.sauce.ts` used 49,931 compute units in the simulation below.
* **Heap.** Every cook requests a 256 KiB heap frame, and a program has 64 KiB of working memory per run. The `sauce` command and the SDK's client add the request; a cook assembled by hand must carry it once.
* **Signature fees.** Each signature costs 5,000 lamports. In the simulation below the owner paid 90,672 lamports for the cook: the Kitchen's 85,672 and one signature.
* **Size.** A cook too large for one transaction is staged first ([Bytecode](https://docs.eco.com/sauce/bytecode.md#size)). `sauce tx` then prints a plan of steps: the setup, the cook, then closing the code buffer.

Simulated in the `sauce` command's local copy (LiteSVM) of Solana at slot 460261665, with the current engine and Kitchen and 5 USDC assumed in a Pot not created yet (abridged):

```bash theme={null}
sauce simulate pay.sauce.ts --chain solana --owner <public key> --assume-balance USDC:5 --args <to> 5000000
```

```text theme={null}
The cook succeeds from 9WzD…AWWM: 49931 compute units
  Kitchen create_pot: Pot BjFS…Xo9T is not created on solana yet, so the copy creates it first
  the 759-byte program staged into a code buffer in 3 transactions, as `sauce run` stages it
  the cook from that buffer, from the owner 9WzD…AWWM, which pays the Kitchen's execution fee of 85672 lamports
```

## Next steps

* [`sauce simulate`](https://docs.eco.com/sauce-sdk/cli/simulate), [`sauce tx`](https://docs.eco.com/sauce-sdk/cli/tx) and [`sauce run`](https://docs.eco.com/sauce-sdk/cli/run): every flag of the commands that build a cook.
* [Pot](https://docs.eco.com/sauce/pot.md): where the program runs and where its results end.
* [Security considerations](https://docs.eco.com/sauce/security-considerations.md): what to check before you sign a cook.


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