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

# Run your first Sauce program

> Compile and simulate a USDC payment on Base, build an unsigned transaction, and optionally send it.

This first Sauce SDK walkthrough uses the `sauce` command to prepare a USDC payment on Base. You will create a wallet, write a program, compile it, simulate both success and failure, and build an unsigned transaction. Sending it is an optional final step.

If you want the concepts first, read the [introduction to Sauce](https://docs.eco.com/sauce/introduction.md). For other tasks, browse the [Sauce SDK quickstarts](https://docs.eco.com/quickstarts/sauce/overview.md).

The program runs on a **Pot**, an account that holds its funds. A **cook** is the transaction that runs the program. The wallet you create owns the Pot and pays transaction fees when you send a cook.

Compilation, simulation and transaction building do not sign or send transactions. You can complete those steps without funding the wallet. To follow the same workflow through a coding agent, see [AI agents](https://docs.eco.com/sauce-sdk/ai-agents.md).

## Prerequisites

* Node.js 24 or newer, a terminal, and the `sauce` command from [Installation](https://docs.eco.com/sauce-sdk/installation.md).
* The release's engine deployed on Base. Simulating, building and sending a cook need it, and `sauce pot --chain base --owner <address>` reports whether it is deployed.
* For the optional send step: 1 USDC on Base and enough ETH on Base for gas and the Kitchen fee. Check the simulation's gas usage and the current fee before funding the wallet.
* To send without real funds, run each step with `--chain base-sepolia` instead of `--chain base`: Base Sepolia is a supported testnet, its `USDC` is Circle's testnet USDC and gas is testnet ETH. The Kitchen's execution fee there read 0 on a local fork of Base Sepolia at block 50929446 with the current contracts; `sauce pot --chain base-sepolia --owner <address>` reads the current fee. The program and commands are otherwise the same; simulated on Base Sepolia at block 50914885, the cook paid 1 USDC from a Pot given 5. See [Testnets](https://docs.eco.com/sauce-sdk/cli/chains-and-endpoints.md#testnets).

**1. Create a wallet**

```bash theme={null}
sauce wallet new me
```

The command asks for a password twice (at least 8 characters). It then writes an encrypted keystore to `~/.sauce/wallets/me.json` and prints the address:

```text theme={null}
Created wallet me (EVM): 0xb3614CaCb467102B28114E8aA8f76349d19454f0
  file    ~/.sauce/wallets/me.json
  policy  none (~/.sauce/wallets/me.policy.json would set limits)
```

Your wallet will have its own address; the address above is illustrative. Later commands select this wallet with `--wallet me`. Replace `<recipient>` with the address that should receive the payment. For this exercise, you can use your new wallet's address.

This is a hot wallet: keep small balances in it. A policy file can cap what it sends ([Wallets, passwords and spending policy](https://docs.eco.com/sauce-sdk/cli/wallets-and-policy.md)).

**2. Write the program**

`pot` is your Pot, available without declaring it, and `pot.USDC` is its USDC balance ([Names](https://docs.eco.com/sauce/names.md#balances)).

Save this as `pay.sauce.ts`:

```ts pay.sauce.ts theme={null}
// Pays `amount` of USDC from your Pot to `to`, and reverts if the Pot holds less.
//
//   sauce simulate pay.sauce.ts --chain base --wallet me --assume-balance USDC:5 --args <recipient> 1000000
//   sauce run pay.sauce.ts --chain base --wallet me --args <recipient> 1000000
//
//   to: Address       who receives the USDC
//   amount: Uint256   USDC in its smallest unit (6 decimals): 1000000 is 1 USDC
function main(to: Address, amount: Uint256) {
  require(pot.USDC >= amount, "not enough USDC");
  USDC.transfer(to, amount);
}
```

* `main`'s parameters are the program's inputs. You pass them with `--args`, in order.
* `USDC` needs no import and no address: it resolves to USDC's address on the chain you compile for.
* `require` reverts the whole cook when its condition is false.
* `USDC.transfer` pays from the Pot, with the checks of OpenZeppelin's `SafeERC20`.

**3. Compile it**

```bash theme={null}
sauce compile pay.sauce.ts --chain base
```

The output is the program's bytecode, one line of hex:

```text theme={null}
0xa502011fd1514702000eb19000b6d00200df01209554e10200ff01209554010014833589fcd6edb6e08f4c…
```

A mistake in the file prints an error with its line and column instead. The same file compiles for Solana with `--chain solana`.

**4. Simulate it**

```bash theme={null}
sauce simulate pay.sauce.ts --chain base --wallet me --assume-balance USDC:5 \
  --args <recipient> 1000000
```

This command does not sign or send anything:

* It reads Base's current state, through a built-in public endpoint unless you pass `--rpc-url` or `--config`.
* It gives your Pot 5 USDC for this simulation only (`--assume-balance USDC:5`).
* It runs the cook from your wallet's address. `--wallet me` only names the owner, so no password is needed.

```text theme={null}
The cook succeeds from 0xb3614CaCb467102B28114E8aA8f76349d19454f0: gas used 105191 for the cook, after the Pot's deploy (1. below), returns 0x
Left in the Pot, not in the owner's wallet:
  4 USDC (it held 5 USDC before)
Simulated with eth_simulateV1 on the state of block <block>; nothing was signed or sent:
  1. Kitchen.deployPot(0xb3614CaCb467102B28114E8aA8f76349d19454f0, 0x0000…0000), gas used 667003: Pot 0xD00C2f93917347fE1ADFbe831Bc62C30d93c79f2 is not deployed on base yet, so the simulation deploys it first …
  2. the cook, from the owner 0xb3614CaCb467102B28114E8aA8f76349d19454f0, gas used 105191
What moved, in order:
  [1] wallet 0xb361…54f0 -> Pot 0xD00C…79f2      0.00000374478538635 ETH  the cook's value
  [2] Pot                -> Kitchen <Kitchen>    0.00000374478538635 ETH  the Kitchen's fee
  [3] Pot                -> wallet               1 USDC
```

This illustrative report uses the owner's wallet as the recipient. The transfers happen in order:

* **\[1]** The wallet sends the fee to the Pot as the cook's value.
* **\[2]** The Pot pays the Kitchen's execution fee.
* **\[3]** The Pot pays 1 USDC to the recipient.

Because this Pot is not deployed yet, the simulation deploys it first, as `sauce run` would. Actual gas usage and fees depend on chain state.

Now give the Pot less than the amount:

```bash theme={null}
sauce simulate pay.sauce.ts --chain base --wallet me --assume-balance USDC:0.5 \
  --args <recipient> 1000000
```

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

The command exits with status 1. The `require` reverted the cook, so nothing would move.

**5. Build an unsigned transaction**

`sauce tx` prints unsigned transactions as JSON. Replace `<owner>` with the address of the wallet you created, so the plan uses the same Pot as your simulation:

```bash theme={null}
sauce tx pay.sauce.ts --chain base --owner <owner> --args <recipient> 1000000
```

If the Pot is not deployed yet, the command prints a plan of two transactions to send in order:

1. the Kitchen's `deployPot`, which any account may send;
2. the cook, which only the owner may send.

Abridged example output (addresses and values vary):

```json theme={null}
{
  "chainId": 8453,
  "pot": "0xD00C2f93917347fE1ADFbe831Bc62C30d93c79f2",
  "transactions": [
    {
      "what": "Kitchen.deployPot(0xb3614CaCb467102B28114E8aA8f76349d19454f0, 0x00…",
      "deploysPot": "0xD00C2f93917347fE1ADFbe831Bc62C30d93c79f2",
      "chainId": 8453,
      "to": "<Kitchen>",
      "data": "0xff9763ac…",
      "value": "0x0"
    },
    {
      "what": "cook on Pot 0xD00C2f93917347fE1ADFbe831Bc62C30d93c79f2",
      "chainId": 8453,
      "to": "0xD00C2f93917347fE1ADFbe831Bc62C30d93c79f2",
      "data": "0xb38dbf14…",
      "value": "0x367e69a4b6e"
    }
  ],
  "sendCalls": { "chain": "base", "calls": [ … ] }
}
```

The `value` of the cook is the Kitchen's execution fee in wei, read from the chain. `sendCalls` holds both transactions as one batch, for a wallet that sends batches. Notes on stderr explain the prerequisites for sending: the Pot must be funded once it is deployed, and its owner must send the cook. You can stop here if you only want to build a transaction. To send it, put 1 USDC and enough ETH for gas and the Kitchen fee in your wallet, and build the plan again with `--fund USDC:1`, which transfers 1 USDC from the wallet into the Pot after its deployment and before the cook, then sign the plan with your wallet.

**6. Optional: send with sauce run**

This step spends real funds. Fund your wallet's address (`sauce wallet address me`) with enough ETH on Base for gas and the Kitchen fee, and check the requirements with the simulation and with `sauce pot --chain base --wallet me`, which reads the Kitchen's fee and whether the engine and Kitchen are deployed. Then deploy your Pot, which sends the deployment and waits for the Pot's code:

```bash theme={null}
sauce pot --chain base --wallet me --deploy
```

Send 1 USDC on Base to the `"pot"` address it prints. Deploy before you send funds: until the Pot is deployed, its address is a prediction that a Kitchen upgrade can move ([Funding a Pot](https://docs.eco.com/sauce-sdk/cli/funding.md)). Then:

```bash theme={null}
sauce run pay.sauce.ts --chain base --wallet me --args <recipient> 1000000
```

`sauce run` then does the following:

1. Asks for the wallet's password.
2. Checks the Pot. A Pot with no code yet is deployed first, after you approve it, in a transaction of its own.
3. Simulates the cook, signs it, sends it and waits for the receipt.
4. Prints the hash, the status and the gas used. If the cook reverts, it prints the decoded reason and exits with status 1.

For scripts or CI, configure a password source and explicit approvals as described in [sauce run](https://docs.eco.com/sauce-sdk/cli/run.md). The command stops when it needs an interactive answer that it cannot obtain.

## What you built

* The program compiled to bytecode for V12, the Sauce engine. The engine runs that bytecode; you do not deploy a separate contract for the program.
* The cook is a transaction to your Pot. If you send it successfully, the Pot runs the program, pays the recipient and pays the Kitchen its fee.
* If the `require` fails, the whole cook reverts and only the gas is spent. The program catches no failure, so any failed call would revert it the same way.
* Tokens left in the Pot stay there until a later cook moves them.

## Troubleshooting

* **The engine is not deployed:** compilation still works, but simulation and execution require the matching release on Base. See [deployment troubleshooting](https://docs.eco.com/sauce-sdk/operating/troubleshooting.md#release-not-deployed-and-engine-pairing).
* **The program reports `not enough USDC`:** an assumed balance applies only to simulation. Deploy and fund the Pot before sending, or use [funding in the cook](https://docs.eco.com/sauce-sdk/cli/funding.md), which deploys the Pot first.
* **RPC calls fail:** configure an endpoint with `--rpc-url` or `--config`. See [endpoint troubleshooting](https://docs.eco.com/sauce-sdk/operating/troubleshooting.md#endpoints-and-rate-limits).

## Next steps

* [AI agents](https://docs.eco.com/sauce-sdk/ai-agents.md): have your coding agent write and simulate programs.
* [sauce simulate](https://docs.eco.com/sauce-sdk/cli/simulate.md) and [sauce run](https://docs.eco.com/sauce-sdk/cli/run.md): every option.
* [Funding a Pot](https://docs.eco.com/sauce-sdk/cli/funding.md): pull tokens into the Pot in the same cook with `--fund`.
* [Compiling programs from TypeScript](https://docs.eco.com/sauce-sdk/typescript/compiling.md): the same steps from your application.
* [Sauce SDK quickstarts](https://docs.eco.com/quickstarts/sauce/overview.md): adapt a complete payment, swap or lending example.


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