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

# Chains, endpoints and fees

> How the sauce command decides which chain it reads and which endpoint it reads it through, for anyone running it against their own RPC.

Every command that reads a chain resolves the chain from `--chain` and reads it through an RPC endpoint. Only on a supported chain does a command build or send a transaction.

## Prerequisites

Simulating a cook, building its transaction and sending it need the release's engine deployed on the chain. `sauce pot` reports whether it is, and what the Kitchen charges:

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

```text theme={null}
On base: the engine <engine address> is deployed; the Kitchen <kitchen address> is deployed, its execution fee 3744785386350 wei (0.00000374478538635 ETH); the Pot <pot address> is NOT deployed.
This is Kitchen.deployPot on the released Kitchen. Any account may send it: the Pot is 0x1111111111111111111111111111111111111111's either way, and it deploys once.
```

The JSON on stdout carries the same facts: `deployment.engine.deployed`, `deployment.kitchen.executionFee` (in wei) and `deployment.pot.deployed`. The addresses are listed on [Deployments](https://docs.eco.com/sauce-sdk/reference/deployments.md). The fee is shown in the chain's native coin beside wei: ETH on Ethereum, Base and their testnets, USDC on Arc and Arc Testnet.

Where the engine has no code on the chain, the first line reads `the engine <engine address> is NOT deployed`, and `pot` adds:

```text theme={null}
The released engine has no code on base: a cook there has nothing to run on.
```

## Supported and preview chains

The registry holds 46 chains. The `sauce` command builds and sends transactions on nine of them, four mainnets and five testnets:

| Chain | Slug | Chain id | Network |
| - | - | - | - |
| Ethereum | `ethereum` | 1 | mainnet |
| Base | `base` | 8453 | mainnet |
| Arc | `arc` | 5042 | mainnet |
| Solana | `solana` | 1399811149 | mainnet |
| Arc Testnet | `arc-testnet` | 5042002 | testnet |
| Base Sepolia | `base-sepolia` | 84532 | testnet |
| Ethereum Sepolia | `sepolia` | 11155111 | testnet |
| Solana Devnet | `solana-devnet` | 1399811150 | testnet |
| Solana Testnet | `solana-testnet` | 1399811151 | testnet |

Every other chain is a preview chain. Preview is a policy on transactions, not on deployment: on a preview chain a program compiles, the reads work, and `simulate` runs wherever the release's engine and Kitchen are deployed, but no transaction is built or sent:

| On a preview chain | Result |
| - | - |
| `compile`, `actions`, `globals`, `price`, `pools`, `inspect`, `verify` | Same as on a supported chain |
| `simulate` | Runs where the release's engine is deployed, as on a supported chain. Where it is not, exits 1 with `the released engine <engine address> is not deployed on <chain>: this SDK's cook cannot run there` |
| `pot` | Predicts the Pot and, with an endpoint, reads it; the deployment transaction is left out |
| `tx`, `run`, `sign`, `send`, `pot --deploy`, `pot --format cast` | Refused |

A refusal happens before the command reaches any endpoint or reads a key. The command exits 1 and prints the action it refused, the chain, the supported chains, and how to request support for the refused chain. No flag lifts the refusal. [Chains](https://docs.eco.com/sauce-sdk/reference/chains.md) lists every chain with its support.

### Testnets

The release's engine and Kitchen are deployed on the five testnets at their published addresses. Their coins and tokens have no value, so a testnet is where to send a first transaction. Each has built-in public endpoints.

* **Arc Testnet, Base Sepolia and Ethereum Sepolia** register Circle's stablecoins by symbol (`USDC` on all three, `EURC` on Arc Testnet), CCTP (`Cctp.TokenMessenger`) and Circle Gateway (`CircleGateway.GatewayWallet`, `CircleGateway.GatewayMinter`). Their registries have no DEX, lending market or oracle: compile and simulate programs needing those against a mainnet registry that has them. Arc Testnet follows Arc's model: USDC is the native coin behind the ERC-20 `USDC`, and the [fee floor](#the-fee-floor) of 20 gwei applies.

* **No Permit2 on the EVM testnets.** Their registries have no Permit2 entry, so `--fund` of a token in the default `permit2` mode is refused, and you choose another mode ([Funding a Pot](https://docs.eco.com/sauce-sdk/cli/funding.md#testnets-have-no-permit2)). Funding with the native coin alone needs no Permit2.

* **Solana Devnet** (`solana-devnet`, also `devnet`) is a chain of its own. A program compiled for it reads its chain id as 1399811150, and its symbols are devnet's mints (`USDC`, `WSOL`). The Solana venues are mainnet's programs and pools, so a venue name is refused there:

  ```text theme={null}
  `Orca.Whirlpool` is not on solana-devnet: the Solana venues are mainnet's programs and pools.
  ```

* **Solana Testnet** (`solana-testnet`, also `testnet`) is a chain of its own too, with id 1399811151. It runs devnet's engine build, so a program compiled for it reads its chain id as 1399811150, as on devnet. Its only symbol is `WSOL`: give any other testnet mint by address, as an `Address` argument of `main` for `Token(mint)`. A venue name is refused there, as on devnet. Its built-in public endpoint is slow to read accounts, and a simulation through it can take minutes; give your own with `--rpc-url` for anything you depend on.

`sauce pot` reports a testnet's deployment and the Kitchen's execution fee as it does a mainnet's. On local forks with the current contracts, of Base Sepolia at block 50929446, Ethereum Sepolia at block 12005429 and Arc Testnet at block 69337859, it read the engine and the Kitchen as deployed and the fee as 0. On Base Sepolia:

```text theme={null}
On base-sepolia: the engine <engine address> is deployed; the Kitchen <kitchen address> is deployed, its execution fee 0 wei (0 ETH); the Pot <pot address> is NOT deployed.
```

The Kitchen's owner sets the fee, so read it with `sauce pot` before you send. The release gives zero execution fees on Solana Devnet and Solana Testnet; `sauce pot --chain solana-devnet --owner <pubkey>` (or `--chain solana-testnet`) reads the current one.

### Example: a cook on Optimism

The examples on this page use a program that reverts unless the Pot holds USDC:

```ts balance.sauce.ts theme={null}
// Requires the Pot to hold some USDC.
// sauce simulate balance.sauce.ts --chain base --owner <owner>
function main() {
  require(USDC.balanceOf(pot) > 0, "no USDC");
}
```

```bash theme={null}
sauce tx balance.sauce.ts --chain optimism --owner 0x1111111111111111111111111111111111111111 --offline
```

```text theme={null}
sauce tx: building the cook transaction is refused: it involves optimism (Optimism, chain id 10), a preview chain. The sauce command and its MCP server build and send transactions only on Ethereum, Base, Arc and Solana, and the testnets Arc Testnet, Base Sepolia, Ethereum Sepolia, Solana Devnet and Solana Testnet. On a preview chain they build and send none. A program still compiles there and globals, price, pools and pot's prediction still read; simulate runs wherever the release is deployed on the chain, and says so where it is not.
```

The refusal is the same with `--offline` and without it, because the command reaches no endpoint before it checks the chain. The second line of the refusal says how to ask for Optimism; it is omitted here.

`sauce simulate` on Optimism runs the cook, and the cook reverts because the Pot holds no USDC:

```bash theme={null}
sauce simulate balance.sauce.ts --chain optimism --owner 0x1111111111111111111111111111111111111111 --json
```

```json theme={null}
{
  "reverted": true,
  "error": "the program threw \"no USDC\"",
  "ok": false,
  "chain": "optimism",
  "block": "158712309",
  "path": "eth_simulateV1",
  "stage": "cook",
  "reason": "the program threw \"no USDC\""
}
```

That is the JSON on Optimism at block 158712309, abridged: it also carries `from`, `to`, `value`, `deployPot` and `assumed`. The command exits 1, as it does for any cook that reverts.

Where the release's engine has no code, `simulate` stops before it simulates. On Avalanche C-Chain a program that compiles there exits 1 with `sauce simulate: the released engine <engine address> is not deployed on avalanche: this SDK's cook cannot run there`; `balance.sauce.ts` stops earlier, because Avalanche's registry has no `USDC`. `sauce pot --chain <chain>` reports whether the engine is deployed on a chain.

### `sauce pot` on a preview chain

`sauce pot` on a preview chain prints the Pot's address, owner, salt and Kitchen, and no `to`, `data` or `value`. Its JSON adds a `refused` object with `code` (`"preview-chain"`), `action`, `message`, `supportedChains` and `previewChains`. The command exits 0.

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

```json theme={null}
{
  "chainId": 10,
  "pot": "<pot address>",
  "owner": "0x1111111111111111111111111111111111111111",
  "salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "kitchen": "<kitchen address>",
  "refused": {
    "code": "preview-chain",
    "action": "building the Pot's deployment",
    "supportedChains": [
      { "slug": "ethereum", "id": 1, "name": "Ethereum" },
      { "slug": "base", "id": 8453, "name": "Base" },
      { "slug": "arc", "id": 5042, "name": "Arc" },
      { "slug": "solana", "id": 1399811149, "name": "Solana" },
      { "slug": "arc-testnet", "id": 5042002, "name": "Arc Testnet" },
      { "slug": "base-sepolia", "id": 84532, "name": "Base Sepolia" },
      { "slug": "sepolia", "id": 11155111, "name": "Ethereum Sepolia" },
      { "slug": "solana-devnet", "id": 1399811150, "name": "Solana Devnet" },
      { "slug": "solana-testnet", "id": 1399811151, "name": "Solana Testnet" }
    ]
  }
}
```

The Kitchen's address is listed on [Deployments](https://docs.eco.com/sauce-sdk/reference/deployments.md).

## Choose a chain with `--chain`

`--chain` takes a chain's slug, one of its aliases, or its numeric chain id. Slugs are matched without regard to case. These lines all compile for Ethereum:

```bash theme={null}
sauce compile balance.sauce.ts --chain ethereum
sauce compile balance.sauce.ts --chain mainnet
sauce compile balance.sauce.ts --chain eth
sauce compile balance.sauce.ts --chain 1
```

The supported chains' aliases:

| Chain | Slug | Aliases |
| - | - | - |
| Ethereum | `ethereum` | `mainnet`, `eth` |
| Base | `base` | none |
| Arc | `arc` | `arc-mainnet`, `arc-network` |
| Solana | `solana` | `sol`, `mainnet-beta`, `solana-mainnet` |
| Arc Testnet | `arc-testnet` | none |
| Base Sepolia | `base-sepolia` | none |
| Ethereum Sepolia | `sepolia` | `ethereum-sepolia`, `eth-sepolia` |
| Solana Devnet | `solana-devnet` | `devnet` |
| Solana Testnet | `solana-testnet` | `testnet` |

Each chain's page under [Chains](https://docs.eco.com/sauce-sdk/reference/chains.md) lists its aliases. An unknown chain exits 2 and lists the known slugs:

```text theme={null}
sauce compile: --chain: Unknown chain 'nowhere' (known slugs: ethereum, optimism, bsc, polygon, base, arbitrum, …, solana, solana-devnet, solana-testnet)
```

`--target <evm|svm>`, where a command takes it, is checked against the chain; `--target svm` with no `--chain` means Solana. A mismatch exits 2:

```text theme={null}
sauce compile: --target svm does not match base, an EVM chain
```

## Endpoints

A command that reads a chain picks its endpoint in this order:

1. `--rpc-url <url>`, the endpoint for the chain the command is for;
2. the `--config <file>` entry for the chain's id;
3. the built-in public endpoints for the chain.

`--rpc-url` and `--config` are exclusive:

```text theme={null}
sauce pot: give --rpc-url or --config, not both
```

The command never prints an endpoint URL you give it, since a provider's URL often carries a key. Before it uses an EVM endpoint, it checks that the endpoint serves the chain you named:

```text theme={null}
sauce pot: the RPC endpoint serves chain 1, but base is 8453
```

### The config file

`--config` takes a JSON file that maps chain ids to endpoint URLs:

```json rpc.json theme={null}
{ "rpcUrls": { "1": "https://ethereum-rpc.publicnode.com" } }
```

```bash theme={null}
sauce pot --owner 0x1111111111111111111111111111111111111111 --chain ethereum --config rpc.json
```

A chain the file does not name is read through the built-in public endpoints. A file without `rpcUrls`, or an entry that is not a URL, exits 2 before anything is read:

```text theme={null}
sauce pot: --config badkey.json: expected { "rpcUrls": { "<chain id>": "<url>" } }
sauce pot: --config placeholder.json: rpcUrls["1"] is not a URL; replace the placeholder
```

The file also takes `"updateCheck": false`, which turns off the update notice for every command that is given this file:

```json rpc.json theme={null}
{
  "rpcUrls": { "1": "https://ethereum-rpc.publicnode.com" },
  "updateCheck": false
}
```

[`sauce init`](https://docs.eco.com/sauce-sdk/cli/init) writes `sauce.config.example.json` with placeholders. Copy it to `sauce.config.json` (the project's `.gitignore` excludes that name) and replace each placeholder with your URL.

### The built-in public endpoints

With no `--rpc-url` and no matching `--config` entry, the command reads the chain through the endpoints built into the package: one to three keyless public endpoints per chain. Each one was checked to answer with the chain's id and to honour state overrides on `eth_call`. Kava, ZetaChain and Evmos have no built-in endpoint. The command prints one line on stderr when it uses them:

```text theme={null}
base: read through a built-in public endpoint, which can be slow or rate-limited; give your own with --rpc-url <url> or --config <file>
```

Requests go through one local forwarder per command, on `127.0.0.1`, which sends each JSON-RPC request to the chain's endpoints in order:

* It moves to the next endpoint when one cannot be reached, gives no answer within 8 seconds, refuses the request (401, 403), rate-limits it (429) or fails (5xx).
* It keeps to the endpoint that last answered, so one command reads one node's view of the chain until that node fails.
* It sends `eth_simulateV1` only to endpoints known to run it, and Solana `getProgramAccounts` scans only to endpoints known to answer them.

Public endpoints can be slow or rate-limited. Use your own endpoint for anything you depend on.

### `eth_simulateV1` and the `eth_call` fallback

`sauce simulate` simulates an EVM cook with `eth_simulateV1` where the endpoint serves it. That one simulated block holds the Pot's deployment when the Pot has none yet, the approvals and transfers sent before the cook, then the cook. It returns the cook's logs, so the output lists token transfers, approvals and traced native transfers.

An endpoint that does not serve `eth_simulateV1` falls back to `eth_call` with state overrides, which gives the result and the gas but no logs. The JSON output names the path it took in `path`:

```json theme={null}
{
  "chain": "base",
  "block": "<block>",
  "path": "eth_simulateV1",
  "stage": "cook",
  "reason": "the program threw \"no USDC\""
}
```

A wallet policy's token limits need `eth_simulateV1`: without it, what a transaction moves is not measured, and a send that a limit applies to is refused.

## `--offline`

`--offline` reaches no endpoint, not even a built-in one, and turns off the update check. A command whose output needs the chain refuses it:

```text theme={null}
sauce simulate: --offline reads no chain, and this reads base
```

`sauce compile` runs the same with `--offline`. `sauce pot --offline` predicts the Pot without reading it. `sauce tx --offline` needs `--value`, because it cannot read the Kitchen's fee:

```text theme={null}
sauce tx: missing --value <wei>: the cook pays the Kitchen's execution fee plus any native the program spends. Pass it, or an RPC endpoint (--rpc-url or --config) to read the fee.
```

```bash theme={null}
sauce tx balance.sauce.ts --chain base --owner 0x1111111111111111111111111111111111111111 --value 0 --offline
```

A command that never reads a chain, such as `sauce globals`, does not take `--offline`, and its error lists the commands that do.

## Arc

Arc's native coin is USDC. Gas, a cook's `value` and the Kitchen's execution fee are paid in it.

| Fact | Value |
| - | - |
| Native coin | USDC, 18 decimals (`msg.value`, `eth_getBalance`, gas) |
| ERC-20 `USDC` | 6 decimals, the same balance as the native coin |
| Minimum base fee | 20 gwei |

The native coin and the ERC-20 `USDC` are one balance at two scales. Sending native value and calling `USDC.transfer` move the same money:

* `USDC.balanceOf` is the native balance divided by 10^12 and rounded down.
* Native fees paid by the program, such as bridge or messenger fees, spend the Pot's balance. The ordinary cook's Kitchen fee comes from the owner's attached transaction value and is forwarded before the program runs; a [signed cook](https://docs.eco.com/sauce/pot.md#signed-cooks) can pay it from existing Pot funds.
* Every native amount has 18 decimals: a `value` of `1000000` is 10^-12 USDC.
* `sauce pot` shows the Kitchen's execution fee in USDC beside wei: `10000000000000000 wei (0.01 USDC)`.

### The fee floor

A transaction on Arc with a `maxFeePerGas` (or a legacy `gasPrice`) below 20 gwei is never included. On Arc the command applies the floor in two places:

* `sauce tx` and `sauce pot` add a note on stderr when they print an unsigned transaction. The note tells you to sign it with a fee cap at or above the floor:

  ```text theme={null}
  On arc a transaction is included only with a maxFeePerGas (or gasPrice) of at least 20 gwei, the chain's minimum base fee: sign each with a fee cap at or above it, or it is never mined.
  ```

* `sauce send` refuses a signed transaction whose fee cap is below the floor, before it sends anything, and exits 2:

  ```text theme={null}
  sauce send: transaction 1 is signed with a fee cap of 1 gwei, below arc's minimum base fee of 20 gwei, so it would never be included: sign it again with a maxFeePerGas of at least 20 gwei. Nothing was sent
  ```

Arc and Arc Testnet are the only chains in the registry with a minimum base fee. The command applies no fee floor on any other chain. On Arc Testnet, `sauce pot` and `sauce tx` print the note with `arc-testnet` in place of `arc`.

[Arc](https://docs.eco.com/sauce-sdk/reference/chains/arc.md) lists Arc's tokens and protocols.

## Next steps

* [The sauce command](https://docs.eco.com/sauce-sdk/cli/overview.md)
* [Chains](https://docs.eco.com/sauce-sdk/reference/chains.md)
* [Deployments](https://docs.eco.com/sauce-sdk/reference/deployments.md)
* [`sauce simulate`](https://docs.eco.com/sauce-sdk/cli/simulate)
* [`sauce tx`](https://docs.eco.com/sauce-sdk/cli/tx)
* [`sauce send`](https://docs.eco.com/sauce-sdk/cli/send)


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