Skip to content

Conversation

@0xrusowsky
Copy link
Contributor

@0xrusowsky 0xrusowsky commented Aug 7, 2025

Motivation

ref: #11078

Solution

this PR introduces a new [fork] section in foundry.toml to configure all the necessary variables to easily deal with multi-chain tests and scripts.

[forks]

[forks.mainnet]
rpc_url = "${MAINNET_RPC_URL}" # Optional. If uninformed, it is auto-derived from `[rpc_endpoints]`

[forks.mainnet.vars]
weth = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
usdc = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
pool_name = "USDC-WETH"
pool_fee = 3000

[forks.arbitrum]
rpc_url = "${ARBITRUM_RPC_URL}" # Optional. If uninformed, it is auto-derived from `[rpc_endpoints]`

[forks.arbitrum.vars]
weth = "0x4200000000000000000000000000000000000006"
usdc = "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
pool_name = "WETH-USDC"
pool_fee = 100

this configuration is then made available at runtime with a new set of cheatcodes:

// Access to all the configured chains, by name or id
function forkChains() external view returns (string[] memory);
function forkChainIds() external view returns (uint256[]);

// Read the configured variables for a given chain and cast them a given type
function forkChainRpcUrl(uint256 id) external view returns (string memory);
function forkChainAddress(uint256 chain, string memory key) external view returns (address);
function forkChainBool(uint256 chain, string memory key) external view returns (bool);
function forkChainBytes(uint256 chain, string memory key) external view returns (bytes memory);
function forkChainBytes32(uint256 chain, string memory key) external view returns (bytes32);
function forkChainInt(uint256 chain, string memory key) external view returns (int256);
function forkChainUint(uint256 chain, string memory key) external view returns (uint256);
function forkChainString(uint256 chain, string memory key) external view returns (string memory);

// Same as above, but directly derive the chain id from the currently active fork
function forkRpcUrl() external view returns (string memory);
function forkChain() external view returns (string memory);
function forkChainId() external view returns (uint256);
function forkAddress(string memory key) external view returns (address);
function forkBool(string memory key) external view returns (bool);
function forkBytes(string memory key) external view returns (bytes memory);
function forkBytes32(string memory key) external view returns (bytes32);
function forkInt(string memory key) external view returns (int256);
function forkUint(string memory key) external view returns (uint256);
function forkString(string memory key) external view returns (string memory);

PS: these already available cheatcodes are also useful to convert between chain ids and chain names:

/// Information about a blockchain.
struct Chain {
    /// The chain name.
    string name;
    /// The chain's Chain ID.
    uint256 chainId;
    /// The chain's alias. (i.e. what gets specified in `foundry.toml`).
    string chainAlias;
    /// A default RPC endpoint for this chain.
    string rpcUrl;
}

function getChain(string calldata chainAlias) external view returns (Chain memory chain);
function getChain(uint256 chainId) external view returns (Chain memory chain);

@0xrusowsky 0xrusowsky added this to the v1.4.0 milestone Aug 7, 2025
@0xrusowsky 0xrusowsky linked an issue Aug 7, 2025 that may be closed by this pull request
@0xrusowsky 0xrusowsky moved this to Ready For Review in Foundry Aug 8, 2025
@grandizzy
Copy link
Collaborator

grandizzy commented Aug 8, 2025

I am thinking that a nicer devex is to not add the additional fork* cheatcodes but rather update the existing cheatcodes logic to return values for the active fork (if any) - like env* cheatcodes, rpcUrl* etc.

@0xrusowsky
Copy link
Contributor Author

good point, i think this could be better devex!

some questions though, how would that work in practice? 🤔

  1. what if there are collisions between env vars and toml vars? would toml vars win, as they are in an active fork?
  2. the cheatcodes that i proposed also allow to get chain-vars regardless of the active fork. I couldn't think of a specific use-case, but i thought that it could be useful for devs to access vars from other forks for some reason? is this desirable? maybe its overthinking and it can be dropped? if interesting, how should we support it if we use the env* cheats?

@grandizzy
Copy link
Collaborator

good point, i think this could be better devex!

some questions though, how would that work in practice? 🤔

  1. what if there are collisions between env vars and toml vars? would toml vars win, as they are in an active fork?

I think here we should just error to avoid any confusion.

  1. the cheatcodes that i proposed also allow to get chain-vars regardless of the active fork. I couldn't think of a specific use-case, but i thought that it could be useful for devs to access vars from other forks for some reason? is this desirable? maybe its overthinking and it can be dropped? if interesting, how should we support it if we use the env* cheats?

Ah, I see, then makes sense to have such. Maybe then we should just stick with the initial impl you proposed and gather feedback from community re the fork aware cheatcodes I suggested... @zerosnacks wdyt?

@0xrusowsky 0xrusowsky changed the title setup script config env vars feat(cheats): setup script config env vars Aug 9, 2025
@0xrusowsky 0xrusowsky changed the title feat(cheats): setup script config env vars feat(cheats): setup config env vars Aug 9, 2025
@yash-atreya
Copy link
Contributor

yash-atreya commented Aug 12, 2025

I prefer the newly added cheatcodes as well — these make the fork scripting pattern more intentional. Currently, users would vm.selectFork, load env variables, select another fork and load its env variables. This current pattern becomes more prone to misuse when we allow loading arbitrary fork specific variables from config in case a wrong fork is selected. vm.fork(chain, var) pattern solves this.

Impl is looking good.

yash-atreya
yash-atreya previously approved these changes Aug 12, 2025
Copy link
Contributor

@yash-atreya yash-atreya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm! Needs a forge-std PR for the new cheatcodes

@0xrusowsky 0xrusowsky dismissed stale reviews from grandizzy and yash-atreya via eea237a August 12, 2025 07:51
DaniPopes
DaniPopes previously approved these changes Aug 12, 2025
DaniPopes
DaniPopes previously approved these changes Aug 12, 2025
@grandizzy grandizzy self-requested a review August 12, 2025 09:33
@0xrusowsky 0xrusowsky merged commit 2d2ebb0 into master Aug 12, 2025
22 checks passed
@0xrusowsky 0xrusowsky deleted the rusowsky/cheat-script-vars branch August 12, 2025 09:46
@github-project-automation github-project-automation bot moved this from Ready For Review to Done in Foundry Aug 12, 2025
grandizzy added a commit to foundry-rs/forge-std that referenced this pull request Aug 12, 2025
support the new cheatcodes added in
foundry-rs/foundry#11236
support new nonce diffs added in
foundry-rs/foundry#11215

---------

Co-authored-by: grandizzy <[email protected]>
MerkleBoy pushed a commit to MerkleBoy/foundry that referenced this pull request Sep 17, 2025
aubBrooks919 added a commit to aubBrooks919/forge-std that referenced this pull request Sep 25, 2025
support the new cheatcodes added in
foundry-rs/foundry#11236
support new nonce diffs added in
foundry-rs/foundry#11215

---------

Co-authored-by: grandizzy <[email protected]>
davidLong89 added a commit to davidLong89/forge-std that referenced this pull request Sep 25, 2025
support the new cheatcodes added in
foundry-rs/foundry#11236
support new nonce diffs added in
foundry-rs/foundry#11215

---------

Co-authored-by: grandizzy <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Native Multichain Scripting Workflow

5 participants