Skip to content
Open
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
51 changes: 45 additions & 6 deletions src/StdChains.sol
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,13 @@ abstract contract StdChains {

bool private fallbackToDefaultRpcUrls = true;

// The RPC URL will be fetched from config or defaultRpcUrls if possible.
/// @dev Retrieves chain configuration by alias. RPC URL is resolved using the prioritization
/// hierarchy: setChain > foundry.toml > environment variable > defaults.
/// Triggers lazy initialization of default chains on first call.
/// @param chainAlias The chain alias (e.g., "mainnet", "sepolia"). Must match the alias in
/// foundry.toml [rpc_endpoints] section for config-based resolution.
/// @return chain The chain configuration with resolved RPC URL.
/// @custom:reverts If chainAlias is empty or chain not found in the registry.
function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) {
require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string.");

Expand All @@ -79,6 +85,12 @@ abstract contract StdChains {
chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
}

/// @dev Retrieves chain configuration by chain ID. First resolves chainId to its alias via
/// the internal mapping, then delegates to getChain(string). RPC URL resolution follows
/// the same prioritization hierarchy: setChain > foundry.toml > env var > defaults.
/// @param chainId The chain ID (e.g., 1 for mainnet, 11155111 for sepolia).
/// @return chain The chain configuration with resolved RPC URL.
/// @custom:reverts If chainId is 0 or chain not found in the registry.
function getChain(uint256 chainId) internal virtual returns (Chain memory chain) {
require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0.");
initializeStdChains();
Expand All @@ -94,7 +106,13 @@ abstract contract StdChains {
chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
}

// set chain info, with priority to argument's rpcUrl field.
/// @dev Sets custom chain configuration for the given alias. If chain.rpcUrl is provided, it takes
/// priority in subsequent getChain calls. Creates bidirectional mappings (alias <-> chainId).
/// Overwrites existing configuration if the alias already exists.
/// @param chainAlias The chain alias to register (must be non-empty).
/// @param chain The chain data including name, chainId, and optional rpcUrl.
/// @custom:reverts If chainAlias is empty, chainId is 0, or chainId is already mapped to a different alias.
/// @custom:sideeffects Updates chains[chainAlias] and idToAlias[chainId] mappings. Removes old chainId mapping if alias is being updated.
function setChain(string memory chainAlias, ChainData memory chain) internal virtual {
require(
bytes(chainAlias).length != 0,
Expand Down Expand Up @@ -127,7 +145,12 @@ abstract contract StdChains {
idToAlias[chain.chainId] = chainAlias;
}

// set chain info, with priority to argument's rpcUrl field.
/// @dev Convenience overload that accepts a Chain struct instead of ChainData. Extracts the
/// relevant fields and delegates to setChain(string, ChainData). Behavior is identical
/// regarding RPC URL priority and mapping updates.
/// @param chainAlias The chain alias to register (must be non-empty).
/// @param chain The Chain struct including name, chainId, chainAlias, and optional rpcUrl.
/// @custom:reverts Same conditions as setChain(string, ChainData).
function setChain(string memory chainAlias, Chain memory chain) internal virtual {
setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl}));
}
Expand All @@ -146,8 +169,12 @@ abstract contract StdChains {
return string(copy);
}

// lookup rpcUrl, in descending order of priority:
// current -> config (foundry.toml) -> environment variable -> default
/// @dev Internal helper that resolves the RPC URL for a chain using the prioritization hierarchy.
/// Priority order: current chain.rpcUrl > foundry.toml config > environment variable > default.
/// Environment variable format: {UPPERCASE_ALIAS}_RPC_URL (e.g., MAINNET_RPC_URL).
/// @param chainAlias The chain alias used for config and env var lookups.
/// @param chain The chain struct, potentially with an empty rpcUrl to be resolved.
/// @return The chain struct with rpcUrl populated from the highest priority available source.
function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain)
private
view
Expand Down Expand Up @@ -184,10 +211,18 @@ abstract contract StdChains {
return chain;
}

/// @dev Configures whether to fall back to default RPC URLs when foundry.toml config is unavailable.
/// When set to false, getChain will revert if the environment variable is not set and no
/// config exists. Default value is true.
/// @param useDefault If true, falls back to default RPC URLs; if false, requires explicit config or env var.
function setFallbackToDefaultRpcUrls(bool useDefault) internal {
fallbackToDefaultRpcUrls = useDefault;
}

/// @dev Lazy initialization function that populates the default chain registry on first use.
/// Called automatically by getChain and setChain. Uses a guard flag to ensure initialization
/// happens exactly once per contract instance.
/// @custom:chains Initializes 50+ chains including mainnet, testnets, and L2s with default RPC URLs.
function initializeStdChains() private {
if (stdChainsInitialized) return;

Expand Down Expand Up @@ -292,7 +327,11 @@ abstract contract StdChains {
);
}

// set chain info, with priority to chainAlias' rpc url in foundry.toml
/// @dev Internal helper used during initialization to register chains with default RPC URLs.
/// Stores the default URL separately and clears chain.rpcUrl to enable config-based resolution.
/// This ensures foundry.toml and env vars take priority over defaults.
/// @param chainAlias The chain alias to register.
/// @param chain The chain data with a default RPC URL.
function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private {
string memory rpcUrl = chain.rpcUrl;
defaultRpcUrls[chainAlias] = rpcUrl;
Expand Down