sauce simulate on a local fork of Base at block 53122981 with the current contracts.
What a program enforces
Your program enforces the conditions you write, and no others.- A wrong recipient, an amount in the wrong unit and a missing check all compile, and a simulation runs them as written.
- Every token amount is a
Uint256in the token’s smallest unit. USDC has 6 decimals, so1000000is 1 USDC and1is one millionth of a USDC. - Arithmetic is checked: an overflow, an underflow or a division by zero reverts the cook, except in an element an array literal skips. A literal indexed at a literal position runs the element it takes and every element up to and including its last helper call, contract call or token read, in order; it skips the others.
[1 / zero, 7][1]returns 7 forzero0,[1 / zero, pot.USDC][1]reverts, and[pot.USDC, 1 / zero][0]returns the Pot’s USDC (Arrays). A builtin such asMath.mulDivis not a call:[Math.mulDiv(1, 1, zero), 7][1]returns 7. - Use
requirefor a check that must run, and a statement of its own for a call or write that must run. - A use of a name the chain does not have fails the compile, naming the chain; only a test such as
if (UniswapV3.Factory)may name it, and the branch it rules out is not compiled. A missing contract never becomes a zero address at run time. - Take every amount, recipient and limit as a typed
mainparameter, passed with--args, never as a constant edited into the file between runs.
Signed integers
Int256 is the signed integer type. Negative literals, ABI intN outputs and Math.signExtend are Int256, and /, %, >>, <, >, <= and >= are signed on it. A value crossing between Uint256 and Int256 is where a sign goes wrong, so the compiler and the engine check every crossing:
- Conversions are checked.
Uint256(x)reverts whenxis negative, andInt256(x)reverts whenxis 2²⁵⁵ or more.Uint256(delta)withdelta= -5 reverted with no data on the fork. - Mixed arithmetic does not compile.
amount + deltawith aUint256and anInt256is refused; convert one operand first. - Unsigned negation reverts.
-amounton aUint256compiles, and reverts at run time whenamountis not 0. Write-Int256(amount), which returned -5 foramount= 5 on the fork. - The signed minimum divided by -1 reverts.
Int256.fromBits(2 ** 255) / -1overflows; it does not wrap. .fromBits(x)is not a conversion.Int256.fromBitsandUint256.fromBitsreinterpret the bits and check nothing. Use them only when you mean the bit pattern.- Narrow ABI integers are checked. A narrow argument out of its type’s range, and an
intNoruintNoutput whose word is out of range, revert.
signed-delta.sauce.ts
--args 100 -30 it returned 70; with --args 10 -30 the cook reverted with “balance would go below zero”.
A Uint256 and an Int256 in one expression, such as amount + delta, are refused with “cannot combine Uint256 and Int256 in this expression; convert an operand with Int256(value) or Uint256(value) first (conversions check bounds)”. Convert first, as signed-delta.sauce.ts does with Int256(balance).
Atomic reverts and what they do not undo
A program runs inside one transaction. An unhandled failure, such as a failedrequire, a reverting call or an arithmetic error, reverts the whole cook:
- no token moves;
- the Kitchen’s fee is not paid, because it reverts with the rest;
- the gas used up to the failure is spent.
try { … } catch block or .catch(() => { … }) on an external call continues after a failure: the failed work is undone, and the handler runs instead. The next section states what each one undoes. See Errors and reverts.
A revert undoes only the cook’s own transaction. State from earlier transactions stays:
- An allowance your wallet granted earlier, to the Pot or to anyone else, is not revoked when a cook reverts.
- An approval the Pot made in an earlier cook stays in force.
- An approval made in a cook that succeeds outlives the cook. The spender can use what is left of it in any later transaction.
supply.sauce.ts
USDC.approve is a forceApprove. It reads the current allowance and resets a non-zero one to zero before it sets the new amount, so a token that refuses to change one non-zero allowance to another, as USDT does, still works.
Catch boundaries
A caught failure does not revert the cook. The cook succeeds, the Kitchen’s fee is paid, and the program goes on from the handler. What the handler can see, and what was undone, depends on the form.A try block rolls back all of it
A try block of more than one statement commits everything in it on success. On a failure it rolls back the block’s calls, storage writes and variable assignments, unlike JavaScript, and then runs the handler. Work before the block remains.
rollback.sauce.ts
amount 50 returned 2 and moved 0.00005 USDC. amount 200 returned 1008 and moved no USDC: the transfer was undone, stage was back to 1, and the error was the 8 bytes of “too much”. A handler that reads a variable assigned in the block reads its value from before the block.
A single call’s catch covers only the call
try { call } catch, with one external call alone in the block, and <call>.catch(() => { … }) catch that call’s failure only. Evaluating its arguments and decoding its successful return are outside the boundary. A decode that fails, such as a read from an address with no code, reverts the cook. To catch a decode or a check, put it in a block of more than one statement.
Error bytes are untrusted
catch (error) and .catch((error) => { … }) receive the failure’s raw revert bytes, at most the first 256. They can be empty: a bare revert and many arithmetic checks give no data. They can be truncated, and the callee chooses them. Check the length before reading or decoding them. A failure inside the handler is not caught by that handler.
catch-bytes.sauce.ts
A
require message in a program is its revert data as raw bytes, not ABI-encoded. USDC’s revert was ABI-encoded Error(string). Decode by the shape you check, never by assumption.
No finally, and nothing on Solana
There is no finally block: “a finally block is not supported in SauceScript”. On Solana neither try/catch nor .catch() compiles: a program that contains a try block fails with “try/catch is not available on the svm target”. Every failure there reverts the whole cook, so write the conditions as require checks before the call that can fail.
Slippage and price limits
A simulation runs on the chain’s state at one block. Prices move before the cook lands, so a swap carries its own bounds, checked inside the program.minOutis the floor. Every@sauce/routerfunction takesminOut, the least the recipient may receive. Make it amainparameter. In a real run never pass0, which sets no floor. The library’s floor check carries no reason string, so a simulation reports a revert with no data.- Below
minOut, a plain function reverts the whole cook, and atryform may skip instead. Atryform returns0with nothing moved when the shortfall shows before anything moves: a quote belowminOut(tryUniswapV2,tryTraderJoeLB,tryDodoV2,tryWoofi), or a pool that refuses the floor (tryCurve,tryBalancerV2). It also returns0for a pool, pair or Vault with no code. Atryswap through the Router that ran and delivered less still reverts (The try forms). minOutis checked against the amount the venue reports, not the recipient’s balance. The plain functions compare it with the output the pool, the Vault or the Router reports.curveandtryCurvepass it to the pool’sexchangeas its own minimum, and measure the Pot’s balance change only to return and forward what arrived, with no check of that change againstminOut. A token that takes a fee on transfer then delivers less thanminOutto the recipient. Only thetryforms through the Router (tryUniswapV3,tryUniswapV4,tryMaverickV2,tryInfinityCL,tryInfinityBin) measure what the recipient’s balance gained. Where the output token may take a fee, read the recipient’s balance before and after the swap andrequirethe difference.sqrtPriceLimitX96bounds the pool’s price after the swap, not the price you pay. The pool’s fee comes on top: under one limit, the last unit a 1% pool fills costs about 1% more than the limit.sauce priceturns a price into a limit; see thesauce pricecommand.- A limit of
0means no limit.minOutis then the only bound. - A limit on the wrong side of the pool’s price fills nothing. The pool reverts with
SPL. - A price limit can leave input unspent. A pool given more than it fills before its limit takes only what it fills, and the rest of the input stays in the Pot. Every swap leg sends that rest back.
- Venues paid first take the whole input or revert. Uniswap V2 and its forks, Curve, Balancer V2, DODO V2, Trader Joe LB and WOOFi refund nothing.
guarded-swap.sauce.ts
amountIn less what the swap took, measured as the change in the Pot’s balance. It is never the Pot’s whole balance, which can hold more of the token for other uses.
On the fork the 0.05% pool’s price was 2,331.62 USDC per WETH. Selling 2,000 WETH with the limit at 2,328 USDC per WETH filled 14.28 WETH and returned the rest (abridged):
Pot ownership and authority
The table and the points after it describe EVM Pots. Solana has a different trust boundary: the Kitchen is an upgradeable program that signs for every Pot, so its upgrade authority can replace the program that decides who cooks on a Pot, and must be trusted with what every Pot holds. The engine having no upgrade authority does not change that (Trust on Solana).- The owner is fixed when the Pot is created. A
cookfrom any other address reverts withNotOwner(). - Deploying a Pot or funding it grants nothing. The Pot belongs to its owner whoever sends
deployPot, and tokens sent to it can leave only through a cook its owner sends or signs. A Pot has no withdraw function. - An EVM Pot’s code never changes. Nothing upgrades a deployed Pot.
- The engine runs only inside a Pot. On an EVM chain the engine runs only inside a Pot its Kitchen created; called directly, it refuses.
- The fee can change between building and landing. A raised fee fails the cook only if it exceeds the cook’s value, or for a signed cook the smaller of the Pot’s balance and the signed ceiling. The cook then reverts with
FeeNotPaid, and nothing moves.
The Pot’s Router
When a pool calls back during a swap, the call reaches the Pot, and the Pot’s fallback delegatecalls its Router. The Router therefore runs as the Pot, with the Pot’s balances.router() on the Pot returns it.
- A new Pot starts on the Kitchen’s current Router.
setRouter(address)on the Pot changes it. Only the owner can call it; anyone else getsNotOwner().- A Pot created with its Router fixed refuses
setRouterwithRouterFixed(). - Point a Pot only at the Router the Kitchen names (
router()on the Kitchen). Any contract set as the Router runs with the Pot’s balances.
Shared Pots
A Shared Pot has no owner. Anyone can cook on it and spend what it holds, and its Router is always fixed. Fund a Shared Pot and empty it within the same transaction. See Pot.Signed cooks
A Pot created by the current Kitchen runs a cook its owner signed and another account submits, withcookSigned; the owner cancels signatures with invalidateNonces. Pot describes what is signed and what the Pot checks, and sauce sign signs one. A signed cook is a cheque: whoever holds it can cash it, once, until it expires.
- Do not build the signature by hand.
sauce sign, andsignedCookTypedData,encodeCookSignedandverifySignedCookfrom@eco-incorp/sauce/evm/engine, build the EIP-712 data and the call;checkSignedCookPotrefuses a Shared Pot, or a Pot the Kitchen did not create, before you sign. - A signature carries the owner’s full authority. The program it covers runs as the Pot and can move everything the Pot holds, as a cook the owner sends can. Sign only a program you compiled and simulated yourself, with the arguments it will run with.
- A signature is public once it is sent. It is in the transaction’s calldata. A cook that reverts spends nothing, so anyone who holds the signature can send it again until its deadline. Hand it only to the account that should send it.
- Name the submitter when one account should send it. With no submitter, anyone holding the signature may send it, before the account you meant and at a moment of their choosing up to the deadline. The submitter is the Pot’s immediate caller: through a bundler or a forwarding contract, it is that contract.
- Sign short deadlines. The deadline is the last block timestamp at which the cook runs, inclusive. An expired signature is worth nothing to anyone who copied it.
- Cancel what you no longer want.
sauce sign --cancel <nonce>sendsinvalidateNonces(word, mask), and no signature for that nonce runs after it, unless a later cook clears the bit. A cancellation that lands after the cook has run changes nothing. - A later cook can undo a cancellation, and move the Router. The nonce bitmap is ordinary Pot storage, and a program writes the Pot’s storage with
evm.sstore. On a local fork of Base at block 52991146 with the current contracts, a cook ofevm.sstore(slot, 0)at a cancelled nonce’s word (cookNonceSlot(word)) cleared it, and the cancelled signature’s cook then ran. On a Pot whose Router is not fixed, the Router slot is writable the same way: a cook that stored another address there changed whatrouter()returns, which is where the Pot’s fallback goes, withoutsetRouter’s checks. A Pot deployed withdeployPot(owner, salt, true)keeps its Router in its code, and the same write changed nothing there (on a local fork of Base at block 52997615 with the current contracts). Cook only programs you have read, and treat anevm.sstorewhose slot comes from an argument as a write to any of the Pot’s storage. - Sign a fee ceiling you are willing to pay. The Kitchen’s owner may raise the fee after you sign. The Pot pays at most the signed
maxExecutionFee, from its own balance; above it, or above what the Pot holds, the cook reverts withFeeNotPaidand can be sent again once the fee is back under it. - A wallet’s spending limits refuse to sign one. What a signed cook moves is decided when someone else sends it, on the chain’s state then, so a simulation at signing does not measure it. A wallet whose policy sets a
nativeortokenslimit refusessauce sign;chainsandtostill apply (Wallets and spending policy). - The Pot’s errors for a refused signed cook are
BadSignature(),Expired(),NonceUsed(),WrongSubmitter()andFeeNotPaid. Its events areSignedCookandNoncesInvalidated. - A Shared Pot has no owner and refuses every signed cook.
Pots and engine pairing
A Pot runs only with the engines its Kitchen pairs with, and an engine refuses a Pot its paired Kitchen did not create:- A Pot’s address follows from the Kitchen, the owner and the salt. The same owner and salt give a different Pot under a different Kitchen.
- Manage a Pot with the SDK, compiler and engine that pair with its Kitchen.
sauce pot --chain <chain> --owner <address>prints the Pot the installed SDK uses; deploy it (sauce pot --chain <chain> --deployand your signer) before you move anything to it, then review that destination and simulate the move. - Recompile and rebuild. A compiler’s output runs only on the engines its release set records. Recompile every stored program, and rebuild every unsigned transaction you saved, with the installed SDK.
Authorization: ctx.msgSender() and ctx.txOrigin()
The two differ whenever a contract stands between the signer and the Pot. Authorize on
ctx.msgSender(), never on ctx.txOrigin(): a check of the origin passes for any contract the signer calls. ctx.msgSender() is still not proof of who owns the Pot, because a signed cook’s submitter can be a third party. A program that pays the owner takes the recipient as a main parameter. On Solana ctx.txOrigin() does not compile, and ctx.msgSender() is the first signer among the program’s accounts. See Builtins.
Where results end
What a call credits to its caller is credited to the Pot. A swap with no other recipient, Aave’s aTokens supplied forpot and a vault’s shares minted to the Pot all stay in the Pot. They belong to the owner, a wallet app does not show them, and only another cook moves them out.
To deliver a result, name the wallet as the call’s beneficiary (onBehalfOf, receiver, recipient, to) with a main parameter, or transfer it in the same program:
deliver.sauce.ts
sauce simulate lists what a cook leaves in the Pot under “Left in the Pot”. It counts tokens only: a position a protocol keeps in its own books, with no token for it, shows in no balance.
Tokens with unusual behaviour
- No-return tokens. Every token write a program makes through the token syntax follows OpenZeppelin’s SafeERC20 rules:
USDC.transfer,.approve,.transferFrom, the same methods onToken(address), the@sauce/tokenfunctions and the swaps of@sauce/router. A token that returns nothing, as USDT does, works. Afalsereturn, a malformed return or an address with no code reverts the cook. See Names. - Raw ABI writes are not checked. A write through a raw ERC-20 ABI binding is an ordinary bound call. Read, its declared
boolis decoded: USDT’s empty return reverts there, and afalsereturn passes. Discarded, nothing is decoded or checked. Never move tokens that way. See Contracts and ABIs. - Fee-on-transfer and rebasing tokens. A token that charges a transfer fee credits the recipient less than was sent. A rebasing token’s balance changes between transactions, and a transfer of one can credit one unit less than sent. Measure what arrived as a balance change, and pass that on, not the nominal amount.
- Issuer controls. An issuer can pause its token and refuse a sanctioned or blocked address. On Solana a stock mint’s issuer can hold a permanent delegate that can move or burn any balance. A simulation shows the token’s state at its block, not later.
arrived.sauce.ts
Unread call outputs
On an EVM chain, a bound call whose result nothing reads, discarded or kept in a variable never used, skips all decoding and output checks. An empty or malformed successful reply then passes, and so does a call to an address with no code, which succeeds with empty data. The program goes on as if the call had done its work.unread-output.sauce.ts
return UniswapV3.Pool(pool).liquidity(); with the same address reverted with no data, because the empty reply failed to decode.
- Read the result you depend on. Reading any part of a result decodes the whole declared result and checks it.
abi.decodeis always checked. - Check for code where it matters.
ctx.isContract(address)orctx.codeSize(address) > 0before a call whose target must be a contract. - Move tokens with the checked writes.
USDC.transfer,Token(address).transferand the@sauce/tokenfunctions check the reply whether or not the program reads anything. A discarded raw ERC-20 write checks nothing.
checked-read.sauce.ts
Calls to addresses with no code
.catch does not help with an address that has no code. The call succeeds, so there is nothing to catch, and a read result’s decoding is outside the single call’s catch: UniswapV3.Pool(pool).liquidity().catch(() => { return 0; }) with an address that has no code reverted the cook with no data on the fork. Check ctx.codeSize(address) > 0 before calling an address the program is given:
codesize.sauce.ts
.catch is the value form: the constant replaces the result when the call fails. The statement form, a handler that assigns instead of returning, can be refused for a method with a narrow integer output, such as liquidity(), a uint128. UniswapV3.Pool(pool).liquidity().catch(() => { liquid = 0; }); fails with “a .catch() on something other than an external contract call is not supported in SauceScript yet”. Use the value form for those, as codesize.sauce.ts does, or a try block.
ctx.codeSize and ctx.isContract do not compile for Solana, where every account a program touches is listed before it runs.
Names and recorded addresses
- A registry record is not proof of code. The registry records where a contract is deployed; that is not proof that code is at the address today.
sauce potreads whether the released engine and Kitchen are on a chain. Simulate the program to see a missing contract fail. - A chain-qualified name is an address, not a contract to call. In a program compiled for Ethereum,
Base.UniswapV3.Factoryis the address of Base’s factory. Calling it calls that address on Ethereum, and the compiler does not stop the call. - An interface calls whatever is at the address.
UniswapV3.Pool(pool)calls the contract atpool. Where a program pays the contract it calls, take its address from the protocol, asUniswapV3.Factory.getPooldoes in the guard above, rather than from an input.
On Solana
- Accounts are checked by the program. A Solana transaction lists every account it uses. Someone else can build a transaction that puts a different account in a slot, so the compiled program checks each account against what it must be: a token account owned by the named holder, an address derived from its seeds, the expected program. A wrong account fails the whole cook with a reason such as
wrong holder account. - Token-2022 transfer hooks are refused.
@sauce/tokenmoves Token-2022 tokens with the checked transfer, and refuses a mint whose transfer hook names a program before anything moves. Transfer fees, pauses and frozen accounts are applied by the token program; measure what arrived. - Running out of compute fails the whole cook. A transaction has a budget of 1,400,000 compute units. A cook that exceeds it fails, every swap in it with it. Swaps at a price limit on concentrated-liquidity pools spend the most: each pool’s program charges for every tick the swap crosses.
sauce simulateandsauce runstop such swaps short of the budget and check those stops in a simulation;sauce txsimulates nothing, so the cook it builds can differ. - The fee is capped by the cook. A Solana cook carries the most it will pay as the execution fee, and a higher fee refuses the cook before anything runs.
- Rebuild instructions with the installed SDK. The engine’s program id and the Kitchen’s instruction format belong to a release set. Build cooks with the installed SDK; never replay a serialized cook built by another one.
ctx.self()is not the Pot. On Solanactx.self()is the engine’s program id.potis the Pot, andpot.USDCreads its balance. See EVM and Solana.
Agents, wallets and keys
A key that thesauce command or the MCP server signs with is protected by your account’s file permissions and by the password’s source, and by nothing else on the machine.
Where a key is
- A wallet made with
sauce wallet newis a hot wallet: one file,~/.sauce/wallets/<name>.json, mode 0600 in a 0700 directory, holding the key encrypted under a password. An EVM wallet’s file is a standard keystore, so--keystore,cast walletand geth open it too. Whoever can read the file and obtain the password holds the key. Keep small balances in it. - The password comes from the source a command names: an environment variable (
--password-env), a file (--password-file, refused when its group or others can read or write it), a command’s output (--password-command), or the terminal prompt. sauce txprints a cook unsigned, for a hardware wallet or a key service to sign, so the key never reaches this machine.sauce inspecttakes a cook’s data apart against your program file.
What an agent running as you can do
A coding agent’s shell commands, and the MCP server it starts over stdio, run under your user account. Whatever your account can read, so can they. Such an agent can:- Read the key. The wallet files and every password source your account reads (a password file, a
.envfile, an environment variable, what a secret manager’s command prints) are, together, the key. - Sign without the policy. The spending policy applies to
--walletand to the MCP server’s wallet tools.--keystorewith the same wallet file and password,--private-key,cast walletand geth apply none. - Change the policy or the ledger.
<name>.policy.jsonand<name>.ledger.jsonlare your files. A loosened policy lifts its limits, and a deleted ledger counts nothing spent in the last 24 hours. - Read an exported key.
sauce wallet exportrefuses a process with no controlling terminal. A program that runs it in a pseudo-terminal answers its prompt and reads the key. - Enable the MCP server’s wallets.
sauce mcpover stdio with no flags, the entrysauce mcp setupwrites, serves the wallets in~/.sauce/wallets. When it was started without a password source,sauce_wallet_enableenables them from a source the agent names: a variable of the server’s environment, a password file, a.envfile, or a new password the server generates into a new file.sauce_wallet_sendandsauce_signthen sign. The server reads any variable an agent names this way, and uses its value only as the password.
What the spending policy limits
- A send through
--walletorsauce_wallet_sendis simulated before it is signed, and the policy is checked against what the simulation moved. On EVM chains the transaction is measured whole, with the gas and fees it is then signed with, and signed exactly as measured. Nothing on chain enforces the limits: the simulation shows the chain’s head a moment before the send, not the block the transaction lands in. A program that reads that block (its time, its base fee, what another transaction changed first) may move something else there. A bound that must hold in any block is the program’s own, such as arequireon what it sends. tolimits the address a transaction is sent to, and nothing else. A cook is a transaction to the Pot, so a policy that allows the Pot allows whatever its program pays out;nativeandtokenscount what leaves the wallet and the Pot.- An allowance a transaction leaves another key counts as sent, at the whole allowance, with what the transaction moves of the token: on EVM chains an ERC-20’s allowance or one granted through Permit2, read as the chain holds it after the transaction, and on Solana a delegate set or raised. An allowance of a limited token to anyone but the wallet or its own Pot counts only where it is measured exactly, and is refused where it is not. A cook on a Pot whose owner cannot be read is refused where a
nativeortokenslimit applies. - An approval of Permit2 for a limited token is refused: it makes spendable again every Permit2 allowance of that token given before, which the transaction does not report. On a local fork of Base at block 53011315 with the current contracts, a wallet limited to 1 USDC ran a cook that approves Permit2 for the Pot’s USDC and gives another account a 10 USDC Permit2 allowance.
sauce runrefused it, namingtokens.USDC, and sent nothing. Under such a limit, fund with--fund-mode permit,allowanceortransfer. - ERC-721 and ERC-1155 transfers and approvals,
setApprovalForAllincluded, are not limited. Nor is a Token-2022 mint’s permanent delegate that the wallet never held: it moves tokens with no approval from the wallet. - On Windows the command does not check file permissions: a password file, a policy file or the wallet directory that others can read or write is not refused.
Keeping a key from an agent
- Only an account that cannot read the wallet directory and its password source is kept from the key.
sauce mcp --no-walletsserves no wallet tools, and the server over HTTP never signs and has none.- To keep a key off the agent’s machine, sign elsewhere: hand
sauce tx’s unsigned transactions to your own wallet, or let a wallet’s own MCP server sign them (Sign with a wallet’s MCP server).
Simulate before you send
sauce simulate runs the cook from the Pot’s owner on the chain’s current state, or at --block <number>, and signs nothing. Simulate the file you will send, with the arguments you will send, from the owner who will send it. Read three things in the output: what leaves the wallet, what arrives where, and what stays in the Pot.
The supply program above, with 1 USDC assumed in the Pot (abridged):
- The first line gives the result, the gas and
main’s return value, or the reason the cook reverts. - “Left in the Pot” lists each token the cook leaves in the Pot. Here the aTokens stay there.
- “What moved, in order” lists every token transfer and native transfer, the Kitchen’s fee included.
- “Approvals” lists every approval the cook emits. The
allowancecheck in the program shows that none was left standing. - The full report needs an endpoint that serves
eth_simulateV1. Without it the command falls back toeth_call, which gives the result and the gas but no transfers.
--expect-revert <text> turns a simulation into a test of a guard: it exits 0 only when the cook reverts with a reason containing the text. The guard program above with a minOut of 3,000 USDC for 1 WETH:
minOut of 2,300 USDC the same cook succeeded and returned 2330328573, 2,330.33 USDC, so the revert is the floor. A require you write with a message, such as "amountIn is not in the Pot", is matched by its message.
Next steps
- Errors and reverts:
require,throw,tryand.catch. - Types:
Uint256,Int256and their conversions. - Pot and Kitchen: ownership, the Router and the fee.
- The
sauce simulatecommand: every flag. - Glossary: the terms on this page.
