Skip to main content
The Kitchen creates Pots and sets the fee every cook pays. On EVM chains it is a contract, deployed deterministically at the same address on every chain it is on. It is an upgradeable proxy: you call the Kitchen’s address, and its implementation sits behind it. On Solana the Kitchen is a program with the same id on every cluster, and it also stages programs too large for one transaction. Deployments lists the addresses. sauce pot reads a chain’s Kitchen, its fee and an owner’s Pot:
That read was on a local fork of Base at block 52965000 with the current contracts. The JSON on stdout carries the unsigned deployPot transaction.

Creating a Pot

deployPot(owner, salt) creates the Pot of owner under a 32-byte salt, at an address that follows from the Kitchen, the owner and the salt (Pot).
  • Anyone may send it. The Pot belongs to owner, whoever pays for the deployment.
  • It deploys once. Sending it again for the same owner and salt returns the Pot already there.
  • It carries no fee: the deployment costs its gas. On a local fork of Base at block 52965000 with the current contracts, a simulated deployment used 667,003 gas.
  • The Kitchen’s ABI declares the event PotDeployed(owner, salt, pot).
Signed cooks are a feature of the Pots this Kitchen creates, not of the Kitchen (Signed cooks). sauce run deploys an owner’s Pot before the first cook that needs it, and sauce tx puts the deployment first in the plan it prints. sauce pot --deploy sends it on its own. The Kitchen’s functions that create and find Pots:

The fee

Every cook pays the Kitchen a flat fee. It does not depend on what the program does.
  • It is paid in the chain’s native coin. For a cook, it is paid out of the cook’s value, and the Pot forwards it to the Kitchen: what the Pot already holds does not pay it, and native coin the program spends comes on top. For a signed cook, the Pot pays it from its own balance, which includes the value the submitter sent, never more than the signed maxExecutionFee.
  • It is on-chain state. The Kitchen’s owner sets it with setExecutionFee (event ExecutionFeeSet) and withdraws what the Kitchen collected with withdrawExecutionFees.
  • It is read when the cook is built. sauce tx, sauce simulate and sauce run read executionFee(); in TypeScript, kitchenExecutionFee() from @eco-incorp/sauce builds that read and decodes it.
  • A cook below the fee reverts with the Pot’s error FeeNotPaid(uint256 required, uint256 provided): a cook whose value is below it, or a signed cook whose fee is above the smaller of the Pot’s balance and its signed ceiling. A fee raised between building a cook and its landing fails that cook only if the new fee exceeds that bound: the cook’s value, or the smaller of the Pot’s balance and the signed ceiling. Then nothing moves. sauce tx sets the value, and sauce sign the ceiling, to the fee it read, so any increase fails a cook built with those defaults.
  • A cook that reverts pays no fee. The fee transfer reverts with the rest of the transaction.
The fee as sauce pot read it, on local forks with the current contracts, and on Solana as sauce simulate read it from the cluster: On Arc the native coin is USDC, so the fee is paid in USDC: as native value it has 18 decimals, and it is drawn from the same balance as the 6-decimal USDC token. sauce simulate refuses a --value below the fee before it simulates:

What the Kitchen’s owner controls

On EVM chains the Kitchen has an owner, separate from every Pot’s owner. The table and the paragraph after it describe the EVM Kitchen. On Solana the Kitchen’s upgrade authority holds a wider power: see Trust on Solana. The fee has no cap. A fee no cook can pay, or an upgrade whose fee collection reverts, stops every Pot’s cooks, and a Pot has no withdraw function, so what Pots hold stays in them until cooks can run again. The Kitchen’s owner can stop cooks this way, but cannot move what a Pot holds. Changing the Kitchen’s Router moves no Pot address and no deployed Pot. A deployed Pot keeps its Router until its own owner changes it (The Pot’s Router). Only a change of the Pot init-code hash moves the addresses of Pots created afterwards. A release that keeps the Kitchen moves no Pot.

Shared Pots

Every Pot the sauce command and the SDK’s helpers use is a private Pot: one owner, who alone may cook on it. The Kitchen also creates Shared Pots with deploySharedPot(salt).
  • A Shared Pot has no owner. Anyone can cook on it and spend what it holds.
  • So a Shared Pot is funded and emptied within one transaction.
  • Its Router is always fixed.
Encode these calls with v12KitchenAbi from @eco-incorp/sauce/evm/engine, the Kitchen’s complete ABI.

The Kitchen on Solana

On Solana the Kitchen is a program. The engine is named on each call as an account, engine_program; the Kitchen does not check it, and the sauce command names the released engine. Both cooks name the Pot by its salt and then its bump, the byte that makes its address a valid program-derived address, and take the Pot as an account the Kitchen checks against them. The SDK’s builders derive the bump. An instruction serialized for the Kitchen before the current one lacks the bump: build cooks with the installed SDK. The fee lives in one account of the Kitchen, derived from the seed "execution_fee". It is both the price and the treasury: a cook through the Kitchen and a cook directly on the engine read the same fee and pay into the same account.
  • Every cook signs a max_execution_fee, in lamports. A fee above it refuses the cook before anything runs or is paid; the Kitchen’s error is ExecutionFeeExceedsMaximum.
  • A fee payer short of lamports fails a Kitchen cook with ExecutionFeeNotPaid.
  • The fee instructions check the Kitchen program’s live upgrade authority, so whoever can upgrade the Kitchen sets its price (NotFeeAuthority for anyone else).
sauce pot --chain solana prints the Pot’s address, the create_pot instruction, the engine and the Kitchen with its fee, and the Pot’s token accounts:
That is one line of its output for the owner’s default Pot, BjFS…Xo9T (abridged). The lines after it name the Pot’s PYUSD, USDT and WSOL accounts.

Trust on Solana

The Solana Kitchen is an upgradeable program, and it signs for every Pot. The limits of the EVM Kitchen’s owner do not carry over:
  • The Kitchen’s code decides who cooks on a Pot. The current Kitchen requires the Pot’s owner to sign each cook, and then signs for the Pot, so the program can spend what the Pot’s authority covers, its token accounts included.
  • Its upgrade authority can replace that code. A replaced Kitchen could sign for any Pot and run any program on it, so it could move anything a Pot holds. Using a Pot on Solana trusts the Kitchen’s upgrade authority with those funds.
  • The engine has no upgrade authority, so its code cannot change. That does not make the Kitchen immutable: the check of the Pot’s owner, and the signature for the Pot, are the Kitchen’s.
  • The same authority prices the cooks, with set_execution_fee, and collects the fees.
solana program show <program id> prints a program’s upgrade authority, or none. Read on Solana at slot 461689935, the Kitchen’s program data named an upgrade authority, last deployed at slot 460549585; read at slot 461689940, the engine’s named none. Deployments lists both program ids.

Next steps

  • Pot: what the Kitchen creates, and who can do what with it.
  • cook(): the call that pays the fee and runs a program.
  • sauce pot: reading and deploying Pots from the command line.