Skip to content

fix(config): let config-only chains load without an RPC endpoint - #903

Open
zexoverz wants to merge 1 commit into
foundry-rs:masterfrom
zexoverz:fix/config-only-chains
Open

fix(config): let config-only chains load without an RPC endpoint#903
zexoverz wants to merge 1 commit into
foundry-rs:masterfrom
zexoverz:fix/config-only-chains

Conversation

@zexoverz

Copy link
Copy Markdown

The StdConfig constructor resolves an RPC endpoint for every chain section, and fails the whole load when neither endpoint_url nor [rpc_endpoints] supplies one:

try vm.parseTomlString(content, string.concat("$.", chain_key, ".endpoint_url")) returns (string memory url) {
    _rpcOf[chainId] = vm.resolveEnv(url);
} catch {
    _rpcOf[chainId] = vm.resolveEnv(vm.rpcUrl(chain_key));
}

_rpcOf is only read by getRpcUrl, and getRpcUrl is only called by _loadConfigAndForks when it creates forks. So a chain section that exists purely to carry config values is rejected for lacking something nothing on that path would ever read:

[anvil]
endpoint_url = "http://127.0.0.1:8545"

[optimism.uint]
some_number = 7
[FAIL: invalid rpc url: optimism]

This defers the resolution. Loading such a chain now succeeds and its values stay readable. Asking for the endpoint reverts with MissingRpcEndpoint(chainId).

Behaviour change worth flagging

getRpcUrl previously returned an empty string for a chain with no endpoint, and now reverts. That is deliberate, since a caller asking for an endpoint that does not exist is better off knowing than receiving "", and it gives _loadConfigAndForks a failure that names the chain rather than the previous invalid rpc url. Nothing changes for a chain that has an endpoint configured. Happy to return the empty string instead if you would rather keep it non-reverting.

Tests

Two cases in test/Config.t.sol, following the temp-fixture pattern already used by the testRevert_ tests:

  • test_loadConfigWithoutRpcEndpoint loads a config with one endpoint-less chain, asserts both chains load, that the config values are readable, and that a configured endpoint still resolves.
  • testRevert_MissingRpcEndpoint asserts the endpoint lookup reverts for that chain.
forge test                  208 passed, 0 failed
forge fmt --check           clean
forge build --deny warnings clean

Negative control: reverting only the constructor change, leaving the new error declared so it still compiles, makes both new tests fail with invalid rpc url: optimism while the other nine in the file are unaffected.

Context

Reported as foundry-rs/foundry#13119. The premise there does not reproduce on current master: the config in that issue loads fine, empty chain sections are already skipped at StdConfig.sol:100, and a missing type sub-section is already tolerated by the surrounding try ... catch {}. This is the adjacent gap that is real.

The StdConfig constructor resolved an RPC endpoint for every chain section and
failed the whole load when neither endpoint_url nor [rpc_endpoints] supplied
one. _rpcOf is only read by getRpcUrl, and getRpcUrl is only called by
_loadConfigAndForks when it creates forks, so a chain section that exists purely
to carry config values was rejected for lacking something nothing would read.

Resolution is now deferred. Loading such a chain succeeds and its values stay
readable; asking for its endpoint reverts with MissingRpcEndpoint, which names
the chain instead of the previous 'invalid rpc url'.

Reported as foundry-rs/foundry#13119, though the premise there does not
reproduce: the config in that issue loads fine, empty sections are already
skipped and missing type sub-sections are already tolerated. This is the
adjacent gap that is real.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant