- 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.
156 lines
5.7 KiB
JavaScript
Executable File
156 lines
5.7 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Calculate CREATE2 salt to produce a specific contract address
|
|
*
|
|
* CREATE2 formula:
|
|
* address = keccak256(0xff ++ deployer ++ salt ++ keccak256(bytecode))[12:]
|
|
*/
|
|
|
|
const { ethers } = require("ethers");
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
|
|
// Target addresses from genesis.json
|
|
const TARGET_WETH9 = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
|
|
const TARGET_WETH10 = "0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9F";
|
|
|
|
// Load contract bytecode from artifacts
|
|
function loadBytecode(contractName) {
|
|
const artifactsPath = path.join(__dirname, "../../out", contractName, `${contractName}.sol`, `${contractName}.json`);
|
|
if (!fs.existsSync(artifactsPath)) {
|
|
throw new Error(`Artifact not found: ${artifactsPath}`);
|
|
}
|
|
const artifact = JSON.parse(fs.readFileSync(artifactsPath, "utf8"));
|
|
return artifact.bytecode.object;
|
|
}
|
|
|
|
// Calculate CREATE2 address
|
|
function calculateCreate2Address(deployer, salt, bytecode) {
|
|
const bytecodeHash = ethers.keccak256(bytecode);
|
|
const initCodeHash = ethers.keccak256(
|
|
ethers.concat([
|
|
"0xff",
|
|
deployer,
|
|
salt,
|
|
bytecodeHash,
|
|
])
|
|
);
|
|
return ethers.getAddress("0x" + initCodeHash.slice(26));
|
|
}
|
|
|
|
// Find salt that produces target address
|
|
function findSalt(deployer, bytecode, targetAddress, maxIterations = 1000000) {
|
|
console.log(`Finding salt for target address: ${targetAddress}`);
|
|
console.log(`Deployer: ${deployer}`);
|
|
console.log(`Bytecode length: ${bytecode.length} bytes`);
|
|
console.log(`Max iterations: ${maxIterations}`);
|
|
console.log("");
|
|
|
|
// Try common salts first
|
|
const commonSalts = [
|
|
"0x0000000000000000000000000000000000000000000000000000000000000000", // Zero
|
|
"0x0000000000000000000000000000000000000000000000000000000000000001", // One
|
|
"0x000000000000000000000000000000000000000000000000000000000000008a", // Chain ID 138
|
|
ethers.keccak256(ethers.toUtf8Bytes("WETH9")),
|
|
ethers.keccak256(ethers.toUtf8Bytes("WETH10")),
|
|
ethers.keccak256(ethers.toUtf8Bytes("WETH")),
|
|
ethers.keccak256(ethers.toUtf8Bytes("Wrapped Ether")),
|
|
ethers.keccak256(ethers.toUtf8Bytes("ChainID-138-WETH9")),
|
|
ethers.keccak256(ethers.toUtf8Bytes("ChainID-138-WETH10")),
|
|
];
|
|
|
|
console.log("Trying common salts...");
|
|
for (const salt of commonSalts) {
|
|
const address = calculateCreate2Address(deployer, salt, bytecode);
|
|
console.log(` Salt: ${salt.slice(0, 20)}... → Address: ${address}`);
|
|
if (address.toLowerCase() === targetAddress.toLowerCase()) {
|
|
console.log(`\n✅ Found salt: ${salt}`);
|
|
return salt;
|
|
}
|
|
}
|
|
|
|
console.log("\nCommon salts didn't match. Brute forcing...");
|
|
console.log("(This may take a while)");
|
|
|
|
// Brute force
|
|
for (let i = 0; i < maxIterations; i++) {
|
|
const salt = ethers.zeroPadValue(ethers.toBeHex(i, 32), 32);
|
|
const address = calculateCreate2Address(deployer, salt, bytecode);
|
|
|
|
if (i % 10000 === 0) {
|
|
process.stdout.write(`\rChecked ${i} salts...`);
|
|
}
|
|
|
|
if (address.toLowerCase() === targetAddress.toLowerCase()) {
|
|
console.log(`\n✅ Found salt: ${salt} (iteration ${i})`);
|
|
return salt;
|
|
}
|
|
}
|
|
|
|
console.log(`\n❌ Could not find salt after ${maxIterations} iterations`);
|
|
return null;
|
|
}
|
|
|
|
async function main() {
|
|
const args = process.argv.slice(2);
|
|
|
|
if (args.length < 2) {
|
|
console.log("Usage: node calculate-create2-salt.js <contract-name> <deployer-address>");
|
|
console.log("");
|
|
console.log("Examples:");
|
|
console.log(" node calculate-create2-salt.js WETH 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb");
|
|
console.log(" node calculate-create2-salt.js WETH10 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb");
|
|
process.exit(1);
|
|
}
|
|
|
|
const contractName = args[0];
|
|
const deployer = ethers.getAddress(args[1]);
|
|
|
|
let targetAddress;
|
|
if (contractName === "WETH" || contractName === "WETH9") {
|
|
targetAddress = TARGET_WETH9;
|
|
} else if (contractName === "WETH10") {
|
|
targetAddress = TARGET_WETH10;
|
|
} else {
|
|
console.error(`Unknown contract: ${contractName}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
try {
|
|
const bytecode = loadBytecode(contractName);
|
|
const salt = findSalt(deployer, bytecode, targetAddress);
|
|
|
|
if (salt) {
|
|
console.log("");
|
|
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
console.log("✅ CREATE2 Salt Found");
|
|
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
console.log(`Contract: ${contractName}`);
|
|
console.log(`Target Address: ${targetAddress}`);
|
|
console.log(`Deployer: ${deployer}`);
|
|
console.log(`Salt: ${salt}`);
|
|
console.log("");
|
|
console.log("Use this salt in your CREATE2 deployment script!");
|
|
} else {
|
|
console.log("");
|
|
console.log("❌ Could not find salt");
|
|
console.log("You may need to:");
|
|
console.log(" 1. Increase maxIterations");
|
|
console.log(" 2. Check if bytecode matches");
|
|
console.log(" 3. Verify deployer address");
|
|
process.exit(1);
|
|
}
|
|
} catch (error) {
|
|
console.error(`Error: ${error.message}`);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
if (require.main === module) {
|
|
main().catch(console.error);
|
|
}
|
|
|
|
module.exports = { calculateCreate2Address, findSalt };
|
|
|