// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "forge-std/Script.sol"; import "../src/eMoneyToken.sol"; import "./helpers/EnvValidation.sol"; /** * @title AuthorizeUpgrade * @notice Helper script to authorize a token upgrade * @dev This script should be run from a multisig wallet with DEFAULT_ADMIN_ROLE. * IMPORTANT: Only use this after thorough testing and multisig approval. */ contract AuthorizeUpgrade is Script { using EnvValidation for string; function run() external { // Validate environment variables uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); address tokenProxyAddr = vm.envAddress("TOKEN_PROXY_ADDRESS"); address newImplementationAddr = vm.envAddress("NEW_IMPLEMENTATION_ADDRESS"); EnvValidation.validateAddress(tokenProxyAddr, "TOKEN_PROXY_ADDRESS"); EnvValidation.validateAddress(newImplementationAddr, "NEW_IMPLEMENTATION_ADDRESS"); vm.startBroadcast(deployerPrivateKey); address deployer = vm.addr(deployerPrivateKey); eMoneyToken tokenProxy = eMoneyToken(tokenProxyAddr); console.log("=== Authorize Upgrade ==="); console.log("Deployer:", deployer); console.log("Token Proxy:", vm.toString(tokenProxyAddr)); console.log("New Implementation:", vm.toString(newImplementationAddr)); console.log(""); // Verify deployer has DEFAULT_ADMIN_ROLE bytes32 adminRole = tokenProxy.DEFAULT_ADMIN_ROLE(); require( tokenProxy.hasRole(adminRole, deployer), "AuthorizeUpgrade: deployer does not have DEFAULT_ADMIN_ROLE" ); console.log(" [OK] Deployer has DEFAULT_ADMIN_ROLE"); console.log(""); // Verify new implementation has code require(newImplementationAddr.code.length > 0, "AuthorizeUpgrade: new implementation has no code"); console.log(" [OK] New implementation has code"); console.log(""); // Get current implementation address currentImplementation = _getImplementation(tokenProxyAddr); console.log("Current Implementation:", vm.toString(currentImplementation)); console.log("New Implementation:", vm.toString(newImplementationAddr)); console.log(""); // Confirm upgrade console.log("⚠️ WARNING: This will upgrade the token implementation!"); console.log(" Make sure you have:"); console.log(" 1. Validated storage layout compatibility"); console.log(" 2. Tested on testnet"); console.log(" 3. Received multisig approval"); console.log(""); console.log("To proceed, uncomment the following line:"); console.log(" // tokenProxy.upgradeTo(newImplementationAddr);"); console.log(""); // Uncomment the following line to actually perform the upgrade // tokenProxy.upgradeTo(newImplementationAddr); console.log(" [SKIP] Upgrade not executed (commented out for safety)"); console.log(" [INFO] To execute upgrade, uncomment the upgradeTo() call above"); vm.stopBroadcast(); } /** * @notice Gets the implementation address from a UUPS proxy * @param proxyAddr The proxy address * @return implementation The implementation address */ function _getImplementation(address proxyAddr) internal view returns (address implementation) { bytes32 slot = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; assembly { implementation := sload(slot) } } }