- Introduced Aggregator.sol for Chainlink-compatible oracle functionality, including round-based updates and access control. - Added OracleWithCCIP.sol to extend Aggregator with CCIP cross-chain messaging capabilities. - Created .gitmodules to include OpenZeppelin contracts as a submodule. - Developed a comprehensive deployment guide in NEXT_STEPS_COMPLETE_GUIDE.md for Phase 2 and smart contract deployment. - Implemented Vite configuration for the orchestration portal, supporting both Vue and React frameworks. - Added server-side logic for the Multi-Cloud Orchestration Portal, including API endpoints for environment management and monitoring. - Created scripts for resource import and usage validation across non-US regions. - Added tests for CCIP error handling and integration to ensure robust functionality. - Included various new files and directories for the orchestration portal and deployment scripts.
190 lines
7.2 KiB
Solidity
190 lines
7.2 KiB
Solidity
// 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";
|
|
import {CREATE2Factory} from "../contracts/utils/CREATE2Factory.sol";
|
|
|
|
/**
|
|
* @title DeployWETHToGenesis
|
|
* @notice Deploy WETH9 and WETH10 to exact addresses from genesis.json
|
|
* @dev Since addresses are pre-allocated in genesis.json with balance 0x0 and no code,
|
|
* we can deploy directly to them. This script tries multiple strategies:
|
|
* 1. Deploy using CREATE2Factory with calculated salts
|
|
* 2. Deploy directly using CREATE2 with inline assembly
|
|
* 3. Use vm.etch if in fork/test mode
|
|
*/
|
|
contract DeployWETHToGenesis is Script {
|
|
address constant TARGET_WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
|
|
address constant TARGET_WETH10 = 0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9F;
|
|
|
|
// Standard CREATE2 deployer
|
|
address constant CREATE2_DEPLOYER = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
|
|
|
|
function run() external {
|
|
console.log("Deploying WETH9 and WETH10 to genesis addresses...");
|
|
|
|
vm.startBroadcast();
|
|
|
|
// Check if contracts already exist
|
|
if (checkContractExists(TARGET_WETH9)) {
|
|
console.log("WETH9 already deployed at:", vm.toString(TARGET_WETH9));
|
|
verifyWETH9();
|
|
} else {
|
|
console.log("Deploying WETH9...");
|
|
deployWETH9();
|
|
}
|
|
|
|
if (checkContractExists(TARGET_WETH10)) {
|
|
console.log("WETH10 already deployed at:", vm.toString(TARGET_WETH10));
|
|
verifyWETH10();
|
|
} else {
|
|
console.log("Deploying WETH10...");
|
|
deployWETH10();
|
|
}
|
|
|
|
vm.stopBroadcast();
|
|
|
|
console.log("\n=== Deployment Complete ===");
|
|
}
|
|
|
|
function deployWETH9() internal {
|
|
bytes memory bytecode = type(WETH).creationCode;
|
|
|
|
// Strategy 1: Try using CREATE2Factory
|
|
CREATE2Factory factory = new CREATE2Factory();
|
|
console.log("Created CREATE2Factory at:", vm.toString(address(factory)));
|
|
|
|
// Try common salts with the factory as deployer
|
|
uint256 salt = findSaltForDeployer(address(factory), bytecode, TARGET_WETH9);
|
|
|
|
if (salt != type(uint256).max) {
|
|
console.log("Found salt for WETH9:", vm.toString(salt));
|
|
address deployed = factory.deploy(bytecode, salt);
|
|
|
|
if (deployed == TARGET_WETH9) {
|
|
console.log("Successfully deployed WETH9 to target address!");
|
|
verifyWETH9();
|
|
return;
|
|
} else {
|
|
console.log("Deployed to:", vm.toString(deployed), "(not target)");
|
|
}
|
|
}
|
|
|
|
// Strategy 2: Deploy normally (will get random address)
|
|
// Then verify if it matches target (unlikely, but worth checking)
|
|
WETH weth = new WETH();
|
|
console.log("WETH9 deployed at:", vm.toString(address(weth)));
|
|
|
|
if (address(weth) == TARGET_WETH9) {
|
|
console.log("Lucky! Deployed to exact target address!");
|
|
} else {
|
|
console.log("Note: Address does not match target.");
|
|
console.log("These addresses may need to be deployed with specific CREATE2 parameters");
|
|
console.log("or may already exist with different bytecode.");
|
|
}
|
|
}
|
|
|
|
function deployWETH10() internal {
|
|
bytes memory bytecode = type(WETH10).creationCode;
|
|
|
|
// Strategy 1: Try using CREATE2Factory
|
|
CREATE2Factory factory = new CREATE2Factory();
|
|
|
|
// Try common salts with the factory as deployer
|
|
uint256 salt = findSaltForDeployer(address(factory), bytecode, TARGET_WETH10);
|
|
|
|
if (salt != type(uint256).max) {
|
|
console.log("Found salt for WETH10:", vm.toString(salt));
|
|
address deployed = factory.deploy(bytecode, salt);
|
|
|
|
if (deployed == TARGET_WETH10) {
|
|
console.log("Successfully deployed WETH10 to target address!");
|
|
verifyWETH10();
|
|
return;
|
|
} else {
|
|
console.log("Deployed to:", vm.toString(deployed), "(not target)");
|
|
}
|
|
}
|
|
|
|
// Strategy 2: Deploy normally
|
|
WETH10 weth10 = new WETH10();
|
|
console.log("WETH10 deployed at:", vm.toString(address(weth10)));
|
|
|
|
if (address(weth10) == TARGET_WETH10) {
|
|
console.log("Lucky! Deployed to exact target address!");
|
|
} else {
|
|
console.log("Note: Address does not match target.");
|
|
console.log("These addresses may need to be deployed with specific CREATE2 parameters");
|
|
console.log("or may already exist with different bytecode.");
|
|
}
|
|
}
|
|
|
|
function findSaltForDeployer(
|
|
address deployer,
|
|
bytes memory bytecode,
|
|
address target
|
|
) internal pure returns (uint256) {
|
|
bytes32 bytecodeHash = keccak256(bytecode);
|
|
|
|
// Try a wider range of common salts
|
|
for (uint256 i = 0; i < 10000; i++) {
|
|
bytes32 salt = bytes32(i);
|
|
bytes32 hash = keccak256(
|
|
abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)
|
|
);
|
|
if (address(uint160(uint256(hash))) == target) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
// Try some common string-based salts
|
|
bytes32[] memory stringSalts = new bytes32[](10);
|
|
stringSalts[0] = keccak256("WETH9");
|
|
stringSalts[1] = keccak256("WETH10");
|
|
stringSalts[2] = keccak256("WETH");
|
|
stringSalts[3] = keccak256(abi.encodePacked(target));
|
|
stringSalts[4] = bytes32(uint256(138)); // Chain ID
|
|
stringSalts[5] = keccak256(abi.encodePacked("ChainID-138"));
|
|
stringSalts[6] = keccak256(abi.encodePacked(deployer, target));
|
|
stringSalts[7] = bytes32(uint256(uint160(target)));
|
|
stringSalts[8] = bytes32(uint256(uint160(deployer)));
|
|
stringSalts[9] = keccak256(abi.encodePacked(deployer, target, uint256(138)));
|
|
|
|
for (uint256 i = 0; i < stringSalts.length; i++) {
|
|
bytes32 hash = keccak256(
|
|
abi.encodePacked(bytes1(0xff), deployer, stringSalts[i], bytecodeHash)
|
|
);
|
|
if (address(uint160(uint256(hash))) == target) {
|
|
return uint256(stringSalts[i]);
|
|
}
|
|
}
|
|
|
|
return type(uint256).max;
|
|
}
|
|
|
|
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());
|
|
}
|
|
}
|
|
|