From a9babf25fbb97137b4b3dfb042d5102c26f31ade Mon Sep 17 00:00:00 2001 From: Khimesh Dewangan Date: Sat, 11 Jul 2026 23:02:49 +0530 Subject: [PATCH] fix(l2genesis): explicitly initialize WETH storage slots after vm.etch The setWETH() function uses vm.etch to deploy WETH bytecode, which skips constructor execution. While the WETH contract has no constructor side effects (name/symbol are pure L1Block readers, decimals is constant, and mappings correctly start empty), this change makes the initialization explicit by: 1. Zeroing _balanceOf (slot 0) and _allowance (slot 1) via vm.store for clarity 2. Updating the NatSpec comment to document why each storage slot is correct This addresses Lumi audit finding #357 and makes the safety invariant auditable at a glance. Closes #357 --- scripts/L2Genesis.s.sol | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/scripts/L2Genesis.s.sol b/scripts/L2Genesis.s.sol index 46bb72bf7..eff52be15 100644 --- a/scripts/L2Genesis.s.sol +++ b/scripts/L2Genesis.s.sol @@ -275,10 +275,20 @@ contract L2Genesis is Script { } /// @notice This predeploy is following the safety invariant #1. - /// This contract is NOT proxied and the state that is set - /// in the constructor is set manually. + /// This contract is NOT proxied. + /// The WETH contract (src/L2/WETH.sol) has no constructor side effects: + /// - `name()` and `symbol()` are `pure` functions that read from the + /// L1Block predeploy, not from storage. + /// - `decimals` is a `constant` (no storage slot). + /// - `_balanceOf` (slot 0) and `_allowance` (slot 1) are mappings + /// that correctly start empty. + /// We explicitly zero both storage slots after `vm.etch` for clarity, + /// even though the EVM zero-initializes all storage after `vm.etch`. function setWETH() internal { vm.etch(Predeploys.WETH, vm.getDeployedCode("WETH.sol:WETH")); + // Explicitly zero-initialize storage slots for audit clarity: + vm.store(Predeploys.WETH, bytes32(uint256(0)), bytes32(0)); // _balanceOf (slot 0) + vm.store(Predeploys.WETH, bytes32(uint256(1)), bytes32(0)); // _allowance (slot 1) } /// @notice This predeploy is following the safety invariant #2.