// 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 DeployWETHUsingCREATE * @notice Deploy WETH9 and WETH10 using CREATE opcode to match genesis.json addresses * @dev Since addresses are pre-allocated in genesis.json, we can deploy using CREATE * by finding the correct deployer/nonce combination OR by deploying sequentially * from a known deployer until we reach the target addresses. * * This script attempts to deploy using normal CREATE (not CREATE2) which will * produce addresses based on the deployer's nonce. */ contract DeployWETHUsingCREATE is Script { // Target addresses from genesis.json address constant TARGET_WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address constant TARGET_WETH10 = 0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9F; // Deployer from PRIVATE_KEY function run() external { uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); address deployer = vm.addr(deployerPrivateKey); console.log("Deploying WETH9 and WETH10 using CREATE"); console.log("Deployer:", vm.toString(deployer)); console.log("WETH9 target:", vm.toString(TARGET_WETH9)); console.log("WETH10 target:", vm.toString(TARGET_WETH10)); vm.startBroadcast(deployerPrivateKey); // Check current nonce uint256 currentNonce = vm.getNonce(deployer); console.log("Current deployer nonce:", currentNonce); // Check if contracts already exist if (checkContractExists(TARGET_WETH9)) { console.log("WETH9 already exists at target address"); verifyWeth9(); } else { console.log("Deploying WETH9..."); WETH weth9 = new WETH(); address deployedAddress = address(weth9); console.log("WETH9 deployed at:", vm.toString(deployedAddress)); if (deployedAddress == TARGET_WETH9) { console.log("Successfully deployed WETH9 to target address!"); verifyWeth9(); } else { console.log("Deployed to different address"); console.log("Target:", vm.toString(TARGET_WETH9)); console.log("Got:", vm.toString(deployedAddress)); } } if (checkContractExists(TARGET_WETH10)) { console.log("WETH10 already exists at target address"); verifyWeth10(); } else { console.log("Deploying WETH10..."); WETH10 weth10 = new WETH10(); address deployedAddress = address(weth10); console.log("WETH10 deployed at:", vm.toString(deployedAddress)); if (deployedAddress == TARGET_WETH10) { console.log("Successfully deployed WETH10 to target address!"); verifyWeth10(); } else { console.log("Deployed to different address"); console.log("Target:", vm.toString(TARGET_WETH10)); console.log("Got:", vm.toString(deployedAddress)); } } vm.stopBroadcast(); console.log("\n=== Deployment Complete ==="); console.log("Note: If addresses don't match, you may need to:"); console.log(" 1. Use a different deployer address"); console.log(" 2. Adjust deployer nonce to match target addresses"); console.log(" 3. Or use vm.etch in fork/test mode"); } 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()); } }