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

# Funding a Pot

> How to get tokens into a Pot for a program to spend, in the same transaction that runs it.

A program spends what its [Pot](https://docs.eco.com/sauce/pot.md) holds. This page covers the flags that move tokens into the Pot as part of a cook (`--fund`, `--fund-mode`, `--sweep`), the flag that gives a simulation balances the Pot does not hold (`--assume-balance`), and the amount syntax both take.

## Prerequisites

* The `sauce` command: `npm install -g @eco-incorp/sauce`.
* A program that spends from the Pot. The examples use `pay.sauce.ts` from [`sauce compile`](https://docs.eco.com/sauce-sdk/cli/compile#compile-for-base), which pays `amount` of USDC to `to`.
* For a real run, a signer: a wallet from [`sauce wallet`](https://docs.eco.com/sauce-sdk/cli/wallet), a keystore or a key.
* To simulate or run on an EVM chain, the release's engine and Kitchen deployed on the chain, and to run, a chain the `sauce` command sends on. `sauce pot --chain <chain> --owner <address>` reports both, and on a preview chain refuses to build the Pot's deployment.

## Two ways to fund a Pot

* **Send tokens to the deployed Pot**, from any wallet or exchange. On an EVM chain, deploy it first with `sauce pot --chain <chain> --deploy` and your signer; [`sauce pot`](https://docs.eco.com/sauce-sdk/cli/pot) prints its address and whether it is deployed.
* **Pull them in the cook** with `--fund`. The pull, the program and the sweep are one transaction, so they succeed or revert together. `sauce run --fund` deploys a Pot that has no code before it funds it.

> [!WARNING]
>
> On an EVM chain, deploy the Pot before you send it funds from another wallet. An undeployed address is only the Kitchen's prediction. `sauce pot --chain <chain> --deploy`, with your signer, deploys the Pot and waits for its code; `sauce run --fund` deploys it before it funds it. With an endpoint, a `sauce tx --fund` plan puts a token's transfer after the deployment and before the cook. Without an endpoint, including with `--offline`, it checks no deployment and plans no deployment step: deploy the Pot first. `ETH:<amount>` adds to the cook's value, with no separate transfer. Run `sauce pot --chain <chain> --owner <owner>` with an endpoint first: it reports whether the chain has the Kitchen, and on a preview chain it prints a Pot address but refuses the deployment, as the CLI and MCP refuse every transaction there. `--offline` checks neither. [Sweep the Pot](https://docs.eco.com/quickstarts/sauce/sweep-pot.md) recovers funds from a deployed Pot through an owner-authorized cook.

With an endpoint, the command also holds the Pot to the [Pot guard](https://docs.eco.com/sauce-sdk/cli/pot.md#the-pot-guard): a Pot not deployed yet must be where the deployed Kitchen's `predictPot` puts it, and an owner of zero is refused. `sauce run` checks its whole plan before it sends the Pot's deployment, the approvals and the transfers of `--fund`, so none of them is sent when the cook after them would be refused. `sauce pot --offline` prints the address unchecked, and says so.

## The amount syntax

`--fund` and `--assume-balance` take `TOKEN:amount`. `TOKEN` is a registry symbol of the chain (matched without regard to case), a token address, or `ETH` (also `native`) for the chain's native coin.

| You write | It means |
| - | - |
| `USDC:1.5` | 1.5 USDC, in whole tokens, exact through the token's decimals |
| `USDC:2` | 2 USDC: a bare integer is whole tokens too |
| `USDC:1500000` | 1.5 million USDC. A bare integer at or above 10^decimals is still whole tokens, and stderr notes the base-units spelling |
| `USDC:1500000n` | 1,500,000 base units: 1.5 USDC. A trailing `n` marks base units |
| `ETH:0.01` | 0.01 of the native coin, 18 decimals. With `--fund` it is added to the cook's value |
| `0x…:2` | 2 whole tokens of the token at that address, its decimals read from the token |

A symbol the chain does not register is refused with the command that lists the chain's tokens; give the token's address instead. A fraction with `n` is refused:

```bash theme={null}
sauce simulate pay.sauce.ts --chain base --owner 0x1111111111111111111111111111111111111111 \
  --assume-balance USDC:1.5n --args 0x2222222222222222222222222222222222222222 1000000
```

```text theme={null}
sauce simulate: --assume-balance USDC:1.5n: '1.5n' is not an amount — whole tokens (1.5) or base units ending in n (1500000n)
```

A bare integer of base-unit size gets a note and is still read as whole tokens:

```bash theme={null}
sauce simulate pay.sauce.ts --chain base --owner 0x1111111111111111111111111111111111111111 \
  --assume-balance USDC:1500000 \
  --args 0x2222222222222222222222222222222222222222 1000000
```

```text theme={null}
--assume-balance USDC:1500000: that is 1.5 million USDC; for base units write 1500000n
The cook succeeds from 0x1111111111111111111111111111111111111111: gas used 88091 for the cook, after the Pot's deploy (1. below), returns 0x
…
```

`--assume-balance USDC:1500000n` gives the same Pot 1.5 USDC.

## Pull tokens in the cook: `--fund`

`sauce run --fund TOKEN:amount` wraps the program. The new `main` takes the same parameters, pulls each amount from your wallet into the Pot, calls the program's own `main` with the arguments as given, and, with `--sweep`, sends what is left back to you. In a program with no `main`, the pulls go after its imports and the sweep after its last statement. `--fund` is repeatable, one token each.

Before anything is sent, the run checks that your wallet holds each amount. Here `docs` is a throwaway wallet that holds no USDC:

```bash theme={null}
sauce run pay.sauce.ts --chain base --wallet docs --wallets ./wallets --password-file ./pw.txt \
  --pots ./pots --fund USDC:1.5 --sweep --args 0x2222222222222222222222222222222222222222 1000000
```

```text theme={null}
sauce run: 0x2883c72a47e0a86A4E13A048C49b6ADBf1F0D736 holds 0 of USDC (base units), below the 1500000 --fund USDC:1.5 needs
```

Every pull is a `safeTransferFrom`: `@sauce/token`'s, or Permit2's own. Signatures are made locally by the signer you gave.

`--fund` signs and sends only for your own Pot: one the chain shows is yours (its owner you, its address the one a known release's Kitchen gives your owner and salt), or the one the run deploys first. Any other `--pot`, or one whose owner the endpoint cannot read, is refused before anything is signed or sent, by `sauce run` and by `sauce simulate` given your key. A wallet with a [policy](https://docs.eco.com/sauce-sdk/cli/wallets-and-policy.md#funding-a-run-under-a-policy) checks two destinations. The funding is held to `chains` and to `to` with the Pot as the address. Each transaction the run sends before the cook is also held to `to` with its own destination, the token contract: the `approve` of `--fund-mode allowance`, the `transfer` of `--fund-mode transfer`, and the first approval of Permit2 under `--fund-mode permit2`. A policy whose `to` lists only the Pot refuses those three; adding the token's address to `to` lets them through. `permit`, and `permit2` once Permit2 is approved, send nothing before the cook and pass with the Pot alone.

### `--fund-mode`

| Mode | What you sign or send | What stands afterwards |
| - | - | - |
| `permit2` (default) | A Permit2 signature for exactly this amount, to this Pot, once | No allowance for the Pot; your unlimited approval of Permit2 |
| `permit` | The token's own EIP-2612 `permit` signature, for the Pot | Nothing: the pull spends it |
| `allowance` | An `approve` of the Pot for the amount, in a transaction before the cook | The Pot's allowance, until a cook spends it |
| `transfer` | A plain `transfer` to the Pot, in a transaction before the cook | Nothing |

* **`permit2`** works for every ERC-20, USDT included, and keeps the run to one transaction. Each signature names one token, one amount and the Pot as spender, with a fresh nonce and a deadline ten minutes after the latest block.
* **`permit`** needs a token that implements EIP-2612. The run reads the token's domain and checks it against its `DOMAIN_SEPARATOR()`.
* **`allowance`** sets the Pot's allowance from your wallet. A smaller standing allowance is reset to zero first, as OpenZeppelin's `forceApprove` does. If the cook then fails, the allowance stands until a later cook spends it.
* **`transfer`** sends the tokens to the Pot before the cook. If the cook then fails, they stay in the Pot.

`allowance` and `transfer` send a transaction before the cook, outside the cook's atomic revert.

### Testnets have no Permit2

The registries of Arc Testnet, Base Sepolia and Ethereum Sepolia have no Permit2 entry, so a token `--fund` in the default `permit2` mode is refused before anything is signed, and the command exits `2`:

```bash theme={null}
sauce simulate pay.sauce.ts --chain base-sepolia --owner 0x1111111111111111111111111111111111111111 \
  --fund USDC:1 --args 0x1111111111111111111111111111111111111111 1000000
```

```text theme={null}
sauce simulate: Permit2 is not registered on base-sepolia: fund with --fund-mode permit, allowance or transfer
```

Choose the mode yourself there: `--fund-mode transfer` for any ERC-20, `allowance`, or `permit` for a token that implements EIP-2612. With `--fund-mode transfer` the same command succeeds: simulated on Base Sepolia at block 50914243 with no key to sign the pull, the Pot is credited the 1 USDC the transfer would bring. Funding with the native coin alone, such as `--fund ETH:0.001`, rides on the cook's value, needs no Permit2 and works in the default mode. `sauce tx --fund` plans plain transfers and needs no Permit2 either.

### Permit2 and the first-time approval

Under `permit2`, Permit2 moves the tokens, so the first time you fund a token, Permit2 needs your approval for it. That approval is unlimited (`maxUint256`), not the amount you fund. The run asks before it sends it, as it asks before deploying a Pot; `-y` (`--yes`) approves without asking. The approval stands, as Permit2 is designed: each later pull still needs your signature for one amount, to one spender, once.

With no terminal to ask on, or with `--json`, the run sends nothing and names the approval it needs, unless `-y` is given: `-y` approves every pre-cook transaction, including the unlimited Permit2 approval, with no terminal and under `--json`. [`sauce run`](https://docs.eco.com/sauce-sdk/cli/run#what-it-sends-before-the-cook) lists every transaction it asks about.

A wallet whose policy limits the token refuses that approval: approving Permit2 makes every Permit2 allowance of the token you gave before spendable again, which no policy can measure. From such a wallet, fund with `--fund-mode permit`, `allowance` or `transfer`. On a local fork of Base at block 53011315 with the current contracts, a wallet limited to 1 USDC ran `--fund USDC:0.5 --yes` in the default mode:

```text theme={null}
auto-approved: approve Permit2 for USDC
sauce run: refused by the policy of wallet agent (wallets/agent.policy.json): this transaction approves Permit2 (0x000000000022D473030F116dDEE9F6B43aC78BA3) for USDC, which lets each standing Permit2 allowance of it be taken with no further signature, and tokens.USDC limits it
```

Nothing was sent. The same run with `--fund-mode permit` pulled the 0.5 USDC and succeeded.

### `--sweep`

`--sweep` sends the Pot's whole balance of each funded token back to the owner after the program, and of the native coin when `ETH` is funded. It returns everything the Pot holds of those tokens, not only what this run brought.

### `--fund` in `sauce tx`

[`sauce tx --fund`](https://docs.eco.com/sauce-sdk/cli/tx#fund-the-pot-in-the-same-batch) has no modes and no sweep. It adds a plain `transfer` from the owner to the Pot for each token, after the Pot's deployment and before the cook. `ETH:<amount>` is added to the cook's value. A wallet that sends the plan as one batch (`sendCalls`) deploys, funds and cooks with one approval.

## Simulate with balances the Pot does not hold

`--assume-balance TOKEN:amount` sets the Pot's balance for one [`sauce simulate`](https://docs.eco.com/sauce-sdk/cli/simulate) run, by state override. It is repeatable, one token each, and `ETH:<amount>` sets the native balance. The command finds the slot that holds the balance by asking the token, then confirms it with `balanceOf`. A token whose balance is computed rather than stored (rebasing tokens, shares) is refused.

```bash theme={null}
sauce simulate pay.sauce.ts --chain base --owner 0x1111111111111111111111111111111111111111 \
  --assume-balance USDC:5 \
  --args 0x2222222222222222222222222222222222222222 1000000
```

```text theme={null}
…
Assumed for this simulation only, by state override:
  the Pot holds 5 USDC: --assume-balance (its balance word 0x084287d900ad004325a89a942f9a718ace54e0752b69050660ae8cb441df9f1f: Solidity mapping at slot 9)
…
```

`sauce simulate` also takes `--fund`, `--fund-mode` and `--sweep`:

* With the owner's key (`--wallet`, `--keystore` or `--private-key`), it signs the pulls `sauce run` would make and sends nothing. An approval the run would ask for is reported and simulated before the cook.
* With `--owner` and no key, the pulls cannot be signed. The Pot is credited what they would bring, `--sweep` still runs, and a shortfall in the owner's wallet is noted rather than refused.

On Solana, `--fund` is not available. `--assume-balance` makes the simulation run in a local copy of the accounts, where the account the cook spends the token from is given the balance.

## On Arc: USDC is the native coin

Arc's native coin is USDC. The chain's gas, a cook's value and the Kitchen's fee are paid in it, and it is the same balance as the `USDC` ERC-20: 18 decimals as native value, 6 through the token. The command treats the two as one:

| On Arc | Effect |
| - | - |
| `--assume-balance ETH:5` (or `native:5`) | The Pot holds 5 native USDC |
| `--assume-balance USDC:5` | The same: the Pot's native balance, since no token storage holds it |
| `--assume-balance USDC:5 --assume-balance ETH:1` | Refused: `--assume-balance names USDC twice: give it once` |
| `--fund USDC:1` in a simulation with no key | Credits the Pot's native balance |
| `sauce tx --fund USDC:2` | A `transfer` of 2000000 base units through the `USDC` ERC-20 |
| `sauce tx --fund ETH:0.5` | Adds 0.5 USDC to the cook's value, in 18 decimals |

`ETH` on Arc never means ether. `sauce pot` gives the Kitchen's fee in wei and in USDC:

```bash theme={null}
sauce pot --chain arc --owner 0x1111111111111111111111111111111111111111
```

```text theme={null}
On arc: the engine <engine address> is deployed; the Kitchen <kitchen address> is deployed, its execution fee 10000000000000000 wei (0.01 USDC); the Pot 0x6c9175d272D49e6C8C139A3FE6BC6fDb422eD3Fe is NOT deployed.
…
```

In a program, `pot.USDC` reads the Pot's 6-decimal `USDC` token balance on Arc, and `pot.balance` its 18-decimal native balance: the same money at the two scales.

```ts pot-balance.sauce.ts theme={null}
// Returns the USDC the Pot holds, as the 6-decimal token reports it.
//
//   sauce simulate pot-balance.sauce.ts --chain arc --owner <owner> --assume-balance USDC:5
function main(): Uint256 {
  return pot.USDC;
}
```

```bash theme={null}
sauce simulate pot-balance.sauce.ts --chain arc --owner 0x1111111111111111111111111111111111111111 \
  --assume-balance USDC:5
```

Simulated on Arc at block 27999763:

```text theme={null}
The cook succeeds from 0x1111111111111111111111111111111111111111: gas used 60848 for the cook, after the Pot's deploy (1. below), returns 0x00000000000000000000000000000000000000000000000000000000004c4b40
main returns Uint256: 5000000
Left in the Pot, not in the owner's wallet:
  5 USDC (it held 5 USDC before)
…
Assumed for this simulation only, by state override:
  the Pot holds 5 USDC: --assume-balance
What moved, in order:
  [1] wallet 0x1111…1111 -> Pot 0x6c91…D3Fe      0.01 USDC  the cook's value
  [2] Pot                -> Kitchen              0.01 USDC  the Kitchen's fee
Net balance changes:
  0x1111111111111111111111111111111111111111 (owner): -0.01 USDC
  <kitchen address> (Kitchen): +0.01 USDC
```

`--assume-balance USDC:5` set the Pot's native balance, which the token reports as 5000000 in its 6 decimals. With `--json`, the assumed balance is `{ "token": "native", "symbol": "USDC", "amount": "5000000000000000000" }`, in 18 decimals. The cook's value and the Kitchen's fee move as native USDC and each is listed once. `--assume-balance ETH:5` gives the same result. On Arc, `sauce tx` also notes on stderr that a transaction is included only with a `maxFeePerGas` of at least 20 gwei.

## Next steps

* [`sauce simulate`](https://docs.eco.com/sauce-sdk/cli/simulate): read the full simulation report.
* [`sauce run`](https://docs.eco.com/sauce-sdk/cli/run): send a funded cook.
* [`sauce tx`](https://docs.eco.com/sauce-sdk/cli/tx): fund the Pot from another wallet in one batch.
* [Wallets and policy](https://docs.eco.com/sauce-sdk/cli/wallets-and-policy.md): limit what a wallet's runs move.
* [Arc](https://docs.eco.com/sauce-sdk/reference/chains/arc.md): the chain's tokens and protocols.


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