Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions sidebar/guides.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ export const guidesSidebar: Sidebar = {
{ text: "Invariant Testing", link: "/guides/invariant-testing" },
],
},
{
text: "Networks & Payments",
items: [
{ text: "Tempo", link: "/guides/tempo" },
{ text: "MPP-backed RPC Endpoints", link: "/guides/mpp" },
],
},
{
text: "Debugging & Optimization",
items: [
Expand Down
15 changes: 15 additions & 0 deletions src/pages/config/reference/default-config.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,21 @@ offline = false
# Default: "osaka"
evm_version = "osaka"

# Select a non-Ethereum network family for execution.
# Options: "optimism", "tempo"
# Default: none
# network = "tempo"

# Legacy equivalents for the network key are still accepted.
# optimism = true
# tempo = true

# Runtime hardfork for tests and scripts.
# Can be a plain Ethereum hardfork (for example "osaka") or a namespaced
# network hardfork such as "optimism:holocene" or "tempo:T3".
# Default: none
# hardfork = "tempo:T3"

# Whether to activate optimizer
# Default: None
# optimizer = true
Expand Down
40 changes: 40 additions & 0 deletions src/pages/config/reference/testing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,46 @@ The value of `block.number` in tests.

The value of the `chainid` opcode in tests.

##### `network`

- Type: string
- Default: none
- Environment: `FOUNDRY_NETWORK`

Selects the active non-Ethereum network family for tests, scripts, and local execution.

Valid values include:

- `optimism`
- `tempo`

Use this when Foundry is not forking a live RPC endpoint and therefore cannot infer the network from chain ID. Foundry still accepts the legacy boolean forms such as `optimism = true` and `tempo = true`.

```toml
[profile.default]
network = "tempo"
```

##### `hardfork`

- Type: string
- Default: none
- Environment: `FOUNDRY_HARDFORK`

Sets the runtime hardfork for tests and scripts.

This can be either:

- A plain Ethereum hardfork such as `osaka` or `cancun`
- A namespaced hardfork such as `optimism:holocene` or `tempo:T3`

When you use a namespaced hardfork, Foundry also infers the matching network automatically.

```toml
[profile.default]
hardfork = "tempo:T3"
```

##### `gas_limit`

- Type: integer or string
Expand Down
12 changes: 12 additions & 0 deletions src/pages/forge/debugging.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ View logs with `-vv` or higher:
$ forge test -vv
```

For structured output, Foundry also supports `console.table`, which can make repeated values easier to scan than a long sequence of `console.log` lines.

### Labeling addresses

Make traces more readable by labeling addresses:
Expand Down Expand Up @@ -130,3 +132,13 @@ $ forge test -vvv
:::

The trace shows the call hierarchy with the revert bubbling up, and the **Backtrace** pinpoints the exact location in your code.

### Inspecting inheritance linearization

When debugging overrides in a multiple-inheritance hierarchy, inspect the method-resolution order directly:

```bash
$ forge inspect src/MyContract.sol:MyContract linearization
```

This shows the order Solidity uses to resolve inherited functions, which is often the fastest way to understand why a particular override or `super` call is being selected.
15 changes: 15 additions & 0 deletions src/pages/guides/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,21 @@ Practical guides for common workflows and advanced Foundry patterns.
/>
</Cards>

### Networks & Payments

<Cards>
<Card
title="Tempo"
description="Initialize, configure, test, and deploy Foundry projects on Tempo."
to="/guides/tempo"
/>
<Card
title="MPP-backed RPC Endpoints"
description="Use Foundry with HTTP 402 payment-gated RPC endpoints through MPP."
to="/guides/mpp"
/>
</Cards>

### Debugging & Optimization

<Cards>
Expand Down
48 changes: 48 additions & 0 deletions src/pages/guides/invariant-testing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,54 @@ fail_on_revert = false # Don't fail on handler reverts
shrink_run_limit = 5000 # Attempts to shrink failing sequence
```

### Advanced invariant campaigns

Foundry v1.7.0 added several options that make deep invariant campaigns both faster and more expressive.

#### `check_interval`

Use `check_interval` to trade precision for speed on deep campaigns:

```toml [foundry.toml]
[invariant]
depth = 1000
check_interval = 10
```

This changes when Foundry evaluates the invariant:

- `0` only checks the last call in each run
- `1` checks every call
- `N` checks every `N` calls and always the last call

This is useful when an invariant is expensive to evaluate, but it can miss bugs that break and then restore the invariant between checks.

#### Time-based campaigns

Use `max_time_delay` and `max_block_delay` when bugs depend on elapsed time or block movement between calls:

```toml [foundry.toml]
[invariant]
max_time_delay = 1 days
max_block_delay = 1000
```

Foundry will fuzz both the call sequence and the time or block distance between calls. This is especially useful for vesting, auctions, TWAPs, cooldowns, and any logic that depends on `block.timestamp` or `block.number`.

#### Optimization mode

If an invariant function returns `int256` instead of asserting, Foundry switches from "find a failure" mode to "maximize this value" mode:

```solidity
function invariant_optimize_maxUtilization() public view returns (int256) {
return int256(vault.totalBorrows()) - int256(vault.totalIdle());
}
```

This is a good fit for worst-case slippage, maximum imbalance, largest rounding error, or any other metric you want the fuzzer to push upward.

For optimization-mode campaigns, use a fixed `seed` when you want reproducible results across runs.

### Targeting specific functions

```solidity
Expand Down
88 changes: 88 additions & 0 deletions src/pages/guides/mpp.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
description: Use Foundry with HTTP 402 payment-gated RPC endpoints through the Machine Payments Protocol (MPP).
---

## MPP-backed RPC endpoints

Foundry v1.7.0 can handle HTTP `402 Payment Required` responses from RPC providers that use the Machine Payments Protocol (MPP).

When an RPC endpoint returns `402`, Foundry discovers your Tempo wallet, pays the challenge, and retries the request automatically. Normal RPC URLs keep working as usual; MPP only activates when the endpoint asks for payment.

## Install and configure a wallet

The simplest setup is to install the Tempo CLI and log in once:

```bash
$ curl -fsSL https://tempo.xyz/install | bash
$ tempo wallet login
```

This creates `~/.tempo/wallet/keys.toml`, which Foundry can discover automatically.

If you prefer to provide a single key directly, set `TEMPO_PRIVATE_KEY` instead:

```bash
$ export TEMPO_PRIVATE_KEY=0xabc123...
```

## Make requests against an MPP endpoint

Point any Foundry tool at an MPP-backed RPC URL:

```bash
$ cast block-number --rpc-url https://rpc.mpp.tempo.xyz
```

### Built-in `tempo` and `moderato` fallbacks

Foundry ships with two built-in MPP aliases that work without any `foundry.toml` configuration:

| Alias | Resolves to |
|---|---|
| `tempo` | `https://rpc.mpp.tempo.xyz` |
| `moderato` | `https://rpc.mpp.moderato.tempo.xyz` |

So in a fresh shell you can just do:

```bash
$ cast block-number --rpc-url tempo
$ forge test --fork-url moderato
```

These fallbacks only apply when the alias is not already defined in `[rpc_endpoints]`.

## Configure deposits and local state

Foundry opens and reuses payment channels automatically.

To override the fallback deposit amount for new channels, set `MPP_DEPOSIT`:

```bash
$ MPP_DEPOSIT=500000 cast block-number --rpc-url tempo
```

Open channels are stored in `$TEMPO_HOME/channels.db`.

- If `TEMPO_HOME` is unset, Foundry uses `~/.tempo/channels.db`
- If you are upgrading from older local state, `~/.tempo/foundry/channels.json` is no longer used and channels will be reopened automatically

## Key discovery order

Foundry discovers MPP signing keys in this order:

1. `TEMPO_PRIVATE_KEY`
2. `$TEMPO_HOME/wallet/keys.toml`

When reading `keys.toml`, Foundry prefers:

1. Passkey entries that include an inline signing key
2. Other entries with an inline private key
3. The first matching entry as a fallback

When the server challenge specifies a chain ID or currency, Foundry filters keys to match that challenge before applying the priority rules above.

## Related guides

- [Tempo](/guides/tempo) for project setup and Tempo-specific config
- [MESC](/config/mesc) if you want to manage RPC aliases in a shared config file
- [cast block](/reference/cast/block) and [cast call](/reference/cast/call) for RPC-based workflows
104 changes: 104 additions & 0 deletions src/pages/guides/tempo.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
description: Use Foundry's upstream Tempo support to initialize projects, configure foundry.toml, and work with Tempo transactions.
---

## Foundry on Tempo

Foundry v1.7.0 ships Tempo support in the main `foundry-rs/foundry` release. You no longer need a separate Tempo fork or a special `foundryup` channel.

## Create a Tempo project

Start from the Tempo template when you want the Tempo example contracts, tests, and scripts:

```bash
$ forge init --network tempo my-tempo-app
$ cd my-tempo-app
```

This installs the Tempo template, adds `tempo-std`, and configures the project so Foundry uses Tempo semantics for local execution.

## Configure `foundry.toml`

`forge init --network tempo` now generates a Tempo-ready `foundry.toml` out of the box:

```toml [foundry.toml]
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
network = "tempo"

# Pin a Tempo hardfork when you need deterministic local semantics.
# hardfork = "tempo:T3"

[rpc_endpoints]
tempo = "https://rpc.tempo.xyz/"
moderato = "https://rpc.moderato.tempo.xyz/"
```

What each setting does:

- `network = "tempo"` enables Tempo-specific execution behavior when Foundry is not forking a live Tempo RPC. (The legacy form `tempo = true` is still accepted for back-compat.)
- `[rpc_endpoints]` defines the `tempo` and `moderato` aliases used by `--rpc-url` / `--fork-url`. You can swap the literal URLs for environment variables (e.g. `tempo = "${TEMPO_RPC_URL}"`) if you'd rather not commit them.
- `hardfork = "tempo:T3"` pins tests and scripts to a specific Tempo hardfork. A namespaced hardfork also infers the Tempo network automatically.

If you are forking a live Tempo endpoint, Foundry can usually infer the network from the forked chain ID, so the explicit `network` setting is optional.

## Run tests and scripts

With the config above, commands can refer to Tempo endpoints by alias:

```bash
$ forge test --fork-url moderato
$ forge script script/Mail.s.sol --broadcast --rpc-url moderato
```

You can also deploy directly against a specific endpoint:

```bash
$ forge create src/Mail.sol:Mail \
--rpc-url tempo \
--broadcast \
--private-key $PRIVATE_KEY
```

## Use Tempo transaction features

Tempo-specific transaction options are available across `cast`, `forge create`, and `forge script`.

Common options include:

- `--tempo.fee-token` to pay gas in a TIP-20 token
- `--tempo.nonce-key` to use Tempo's parallelizable nonces
- `--tempo.expiring-nonce`, `--tempo.valid-before`, and `--tempo.valid-after` to time-bound a transaction
- `--tempo.access-key` and `--tempo.root-account` for keychain-based account flows

For example, sending a transaction with a fee token looks like this:

```bash
$ cast send $CONTRACT_ADDRESS "increment()" \
--rpc-url tempo \
--tempo.fee-token $FEE_TOKEN \
--private-key $PRIVATE_KEY
```

## Run Anvil in Tempo mode

Use Tempo network semantics locally when you are not forking a live chain:

```bash
$ anvil --network tempo --hardfork t3
```

When you fork a live Tempo RPC, Foundry can infer the network automatically from the upstream chain ID:

```bash
$ anvil --fork-url $TEMPO_RPC_URL
```

## Related references

- [Configuration reference](/config/reference/testing) for `network` and `hardfork`
- [MPP-backed RPC endpoints](/guides/mpp) for payment-gated Tempo RPCs
- [cast send](/reference/cast/send) for Tempo transaction flags
- [forge create](/reference/forge/create) and [forge script](/reference/forge/script) for deployment flows
10 changes: 7 additions & 3 deletions src/pages/introduction/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,18 @@ $ foundryup --install abc1234
$ foundryup --branch master
```

## Installing forks
## Tempo support

To install binaries from [Tempo's fork](https://github.com/tempoxyz/tempo-foundry):
Tempo support ships in the main Foundry release as of v1.7.0. Install the normal toolchain:

```bash
$ foundryup -n tempo
$ foundryup
```

The old `foundryup -n tempo` / `foundryup --network tempo` flow is deprecated and ignored.

See the [Tempo guide](/guides/tempo) for project setup and [MPP-backed RPC endpoints](/guides/mpp) for paid RPC configuration.

## Binary verification

Foundry binaries are attested using [GitHub artifact attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds). When installing via `foundryup`, binary hashes are automatically verified against the GitHub attestation.
Expand Down