2025-12-12 14:57:48 -08:00
|
|
|
// 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");
|
2026-03-02 12:14:09 -08:00
|
|
|
verifyWeth9();
|
2025-12-12 14:57:48 -08:00
|
|
|
} else {
|
|
|
|
|
console.log("Deploying WETH9...");
|
|
|
|
|
deployWETH9Direct();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (checkContractExists(TARGET_WETH10)) {
|
|
|
|
|
console.log("WETH10 already exists at target address");
|
2026-03-02 12:14:09 -08:00
|
|
|
verifyWeth10();
|
2025-12-12 14:57:48 -08:00
|
|
|
} 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!");
|
2026-03-02 12:14:09 -08:00
|
|
|
verifyWeth9();
|
2025-12-12 14:57:48 -08:00
|
|
|
} 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
|
2026-03-02 12:14:09 -08:00
|
|
|
WETH10 tempWeth10 = new WETH10();
|
|
|
|
|
address tempAddress = address(tempWeth10);
|
2025-12-12 14:57:48 -08:00
|
|
|
|
|
|
|
|
// 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!");
|
2026-03-02 12:14:09 -08:00
|
|
|
verifyWeth10();
|
2025-12-12 14:57:48 -08:00
|
|
|
} 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;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-02 12:14:09 -08:00
|
|
|
function verifyWeth9() internal view {
|
2025-12-12 14:57:48 -08:00
|
|
|
WETH weth = WETH(payable(TARGET_WETH9));
|
|
|
|
|
console.log("WETH9 name:", weth.name());
|
|
|
|
|
console.log("WETH9 symbol:", weth.symbol());
|
|
|
|
|
console.log("WETH9 decimals:", weth.decimals());
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-02 12:14:09 -08:00
|
|
|
function verifyWeth10() internal view {
|
2025-12-12 14:57:48 -08:00
|
|
|
WETH10 weth10 = WETH10(payable(TARGET_WETH10));
|
|
|
|
|
console.log("WETH10 name:", weth10.name());
|
|
|
|
|
console.log("WETH10 symbol:", weth10.symbol());
|
|
|
|
|
console.log("WETH10 decimals:", weth10.decimals());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|