// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import {Script, console} from "forge-std/Script.sol"; import {WETH} from "../contracts/tokens/WETH.sol"; import {WETH10} from "../contracts/tokens/WETH10.sol"; /** * @title DeployWETHToGenesisAddresses * @notice Deploy WETH9 and WETH10 directly to genesis.json addresses using vm.etch * @dev Since addresses are pre-allocated in genesis.json with balance 0x0 and no code, * we can use vm.etch to set the bytecode directly at those addresses. * * This approach works in fork/test mode or if the addresses are empty. */ contract DeployWETHToGenesisAddresses is Script { // Target addresses from genesis.json address constant TARGET_WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address constant TARGET_WETH10 = 0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9F; function run() external { console.log("Deploying WETH9 and WETH10 directly to genesis addresses"); console.log("WETH9 target:", vm.toString(TARGET_WETH9)); console.log("WETH10 target:", vm.toString(TARGET_WETH10)); vm.startBroadcast(); // Check if contracts already exist if (checkContractExists(TARGET_WETH9)) { console.log("WETH9 already exists at target address"); verifyWeth9(); } else { console.log("Deploying WETH9..."); deployWETH9Direct(); } if (checkContractExists(TARGET_WETH10)) { console.log("WETH10 already exists at target address"); verifyWeth10(); } else { console.log("Deploying WETH10..."); deployWETH10Direct(); } vm.stopBroadcast(); console.log("\n=== Deployment Complete ==="); } function deployWETH9Direct() internal { // Deploy to a temporary address first to get the deployed bytecode WETH tempWETH = new WETH(); address tempAddress = address(tempWETH); // Get deployed bytecode from the chain bytes memory deployedBytecode; assembly { let size := extcodesize(tempAddress) deployedBytecode := mload(0x40) mstore(0x40, add(deployedBytecode, add(size, 0x20))) mstore(deployedBytecode, size) extcodecopy(tempAddress, add(deployedBytecode, 0x20), 0, size) } console.log("Got bytecode from temporary deployment"); console.log("Bytecode size:", deployedBytecode.length); // Use vm.etch to set bytecode directly at target address // Note: This works in fork/test mode or if address is empty vm.etch(TARGET_WETH9, deployedBytecode); console.log("Set bytecode at WETH9 address using vm.etch"); // Verify deployment if (checkContractExists(TARGET_WETH9)) { console.log("Successfully deployed WETH9 to target address!"); verifyWeth9(); } else { console.log("Failed to deploy WETH9 - address may not be empty or vm.etch not available"); } } function deployWETH10Direct() internal { // Deploy to a temporary address first to get the deployed bytecode WETH10 tempWeth10 = new WETH10(); address tempAddress = address(tempWeth10); // Get deployed bytecode from the chain bytes memory deployedBytecode; assembly { let size := extcodesize(tempAddress) deployedBytecode := mload(0x40) mstore(0x40, add(deployedBytecode, add(size, 0x20))) mstore(deployedBytecode, size) extcodecopy(tempAddress, add(deployedBytecode, 0x20), 0, size) } console.log("Got bytecode from temporary deployment"); console.log("Bytecode size:", deployedBytecode.length); // Use vm.etch to set bytecode directly at target address vm.etch(TARGET_WETH10, deployedBytecode); console.log("Set bytecode at WETH10 address using vm.etch"); // Verify deployment if (checkContractExists(TARGET_WETH10)) { console.log("Successfully deployed WETH10 to target address!"); verifyWeth10(); } else { console.log("Failed to deploy WETH10 - address may not be empty or vm.etch not available"); } } function checkContractExists(address addr) internal view returns (bool) { uint256 size; assembly { size := extcodesize(addr) } return size > 0; } function verifyWeth9() internal view { WETH weth = WETH(payable(TARGET_WETH9)); console.log("WETH9 name:", weth.name()); console.log("WETH9 symbol:", weth.symbol()); console.log("WETH9 decimals:", weth.decimals()); } function verifyWeth10() internal view { WETH10 weth10 = WETH10(payable(TARGET_WETH10)); console.log("WETH10 name:", weth10.name()); console.log("WETH10 symbol:", weth10.symbol()); console.log("WETH10 decimals:", weth10.decimals()); } }