// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import {Script, console} from "forge-std/Script.sol"; import {MockLinkToken} from "../contracts/tokens/MockLinkToken.sol"; import {CREATE2Factory} from "../contracts/utils/CREATE2Factory.sol"; /** * @title DeployLinkToCanonicalAddress * @notice Attempt to deploy LINK token to canonical Ethereum Mainnet address using CREATE2 * @dev This attempts to find a salt that produces the canonical address 0x514910771AF9Ca656af840dff83E8264EcF986CA * * WARNING: This may not succeed if: * 1. The bytecode doesn't match the original LINK token bytecode * 2. The salt cannot be brute-forced within gas limits * 3. A different CREATE2 factory was used on mainnet */ contract DeployLinkToCanonicalAddress is Script { // Canonical Ethereum Mainnet LINK token address address constant CANONICAL_LINK = 0x514910771AF9Ca656af840dff83E8264EcF986CA; // Maximum salt iterations to try (brute force limit) uint256 constant MAX_SALT_ITERATIONS = 1000000; function run() external { uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); address deployer = vm.addr(deployerPrivateKey); console.log("=== Deploy LINK Token to Canonical Address ==="); console.log("Target Address:", vm.toString(CANONICAL_LINK)); console.log("Deployer:", vm.toString(deployer)); console.log(""); vm.startBroadcast(deployerPrivateKey); // Step 1: Deploy CREATE2Factory (if not already deployed) // For this attempt, we'll deploy a new factory // In production, you might want to use a known factory address CREATE2Factory factory = new CREATE2Factory(); address factoryAddress = address(factory); console.log("CREATE2Factory deployed at:", vm.toString(factoryAddress)); console.log(""); // Step 2: Get LINK token bytecode (creation code) bytes memory linkBytecode = type(MockLinkToken).creationCode; bytes32 bytecodeHash = keccak256(linkBytecode); console.log("LINK Token bytecode hash:", vm.toString(bytes32(bytecodeHash))); console.log(""); // Step 3: Try to find salt that produces canonical address console.log("Searching for salt to match canonical address..."); console.log("This may take some time (max iterations:", MAX_SALT_ITERATIONS, ")"); console.log(""); uint256 foundSalt = 0; bool saltFound = false; // Try different salt values for (uint256 salt = 0; salt < MAX_SALT_ITERATIONS; salt++) { // Compute address for this salt address predictedAddress = factory.computeAddress(linkBytecode, salt); if (predictedAddress == CANONICAL_LINK) { foundSalt = salt; saltFound = true; console.log("SALT FOUND!"); console.log("Salt:", vm.toString(salt)); console.log("Predicted Address:", vm.toString(predictedAddress)); console.log("Target Address:", vm.toString(CANONICAL_LINK)); break; } // Progress indicator every 10000 iterations if (salt > 0 && salt % 10000 == 0) { console.log(" Tried", vm.toString(salt), "salts..."); } } if (!saltFound) { console.log(""); console.log("WARNING: Could not find salt within", MAX_SALT_ITERATIONS, "iterations"); console.log("This means one of the following:"); console.log(" 1. The bytecode doesn't match the original LINK token bytecode"); console.log(" 2. The CREATE2 factory address is different from mainnet"); console.log(" 3. The canonical LINK was deployed using CREATE, not CREATE2"); console.log(" 4. A higher salt value is needed (increase MAX_SALT_ITERATIONS)"); console.log(""); console.log("Recommendation: Use the existing LINK token at different address"); console.log("or verify the original deployment method on Ethereum Mainnet"); vm.stopBroadcast(); return; } // Step 4: Deploy using the found salt console.log(""); console.log("Deploying LINK token using CREATE2..."); address deployedAddress = factory.deploy(linkBytecode, foundSalt); require(deployedAddress == CANONICAL_LINK, "Deployed address doesn't match target"); console.log("LINK token deployed at:", vm.toString(deployedAddress)); console.log(""); // Step 5: Verify the deployment MockLinkToken linkToken = MockLinkToken(deployedAddress); console.log("Verifying deployment..."); console.log(" Name:", linkToken.name()); console.log(" Symbol:", linkToken.symbol()); console.log(" Decimals:", linkToken.decimals()); // Mint initial supply to deployer uint256 initialSupply = 1000000e18; // 1M LINK linkToken.mint(deployer, initialSupply); console.log(" Minted", initialSupply / 1e18, "LINK to deployer"); vm.stopBroadcast(); console.log(""); console.log("=== Deployment Summary ==="); console.log("LINK Token Address:", vm.toString(deployedAddress)); console.log("CREATE2Factory:", vm.toString(factoryAddress)); console.log("Salt Used:", vm.toString(foundSalt)); console.log("Deployer:", vm.toString(deployer)); console.log("Initial Supply:", initialSupply / 1e18, "LINK"); console.log(""); console.log("SUCCESS: LINK token deployed at canonical address!"); } }