129 lines
5.7 KiB
Solidity
129 lines
5.7 KiB
Solidity
|
|
// 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!");
|
||
|
|
}
|
||
|
|
}
|