Arbitrum Timelock
Overview
function name() public pure override returns (string memory) { return "ARBITRUM_L1_TIMELOCK_MOCK"; }function description() public pure override returns (string memory) { return "Mock proposal for upgrading the WETH gateway"; }function deploy() public override { // Deploy new WETH gateway implementation if not already deployed if ( !addresses.isAddressSet("ARBITRUM_L1_WETH_GATEWAY_IMPLEMENTATION") ) { // In a real case, this function would be responsible for // deploying a new implementation contract instead of using a mock address l1NFTBridgeImplementation = address(new MockUpgrade()); addresses.addAddress( "ARBITRUM_L1_WETH_GATEWAY_IMPLEMENTATION", l1NFTBridgeImplementation, true ); } // Deploy new GAC contract for gateway upgrade if not already deployed if (!addresses.isAddressSet("ARBITRUM_GAC_UPGRADE_WETH_GATEWAY")) { address gac = address(new GovernanceActionUpgradeWethGateway()); addresses.addAddress( "ARBITRUM_GAC_UPGRADE_WETH_GATEWAY", gac, true ); } }function preBuildMock() public override { // Deploy new mockOutBox address address mockOutbox = address(new MockOutbox()); // This is a workaround to replace the mainnet outBox with the newly deployed one for testing purposes only vm.store( addresses.getAddress("ARBITRUM_BRIDGE"), bytes32(uint256(5)), bytes32(uint256(uint160(mockOutbox))) ); }function build() public override buildModifier(address(timelock)) { /// STATICCALL -- not recorded for the run stage // Get upgrade executor address IUpgradeExecutor upgradeExecutor = IUpgradeExecutor( addresses.getAddress("ARBITRUM_L1_UPGRADE_EXECUTOR") ); /// CALLS -- mutative and recorded // Upgrade WETH gateway using GAC contract to the newly deployed implementation upgradeExecutor.execute( addresses.getAddress("ARBITRUM_GAC_UPGRADE_WETH_GATEWAY"), abi.encodeWithSelector( GovernanceActionUpgradeWethGateway.upgradeWethGateway.selector, addresses.getAddress("ARBITRUM_L1_PROXY_ADMIN"), addresses.getAddress("ARBITRUM_L1_WETH_GATEWAY_PROXY"), addresses.getAddress("ARBITRUM_L1_WETH_GATEWAY_IMPLEMENTATION") ) ); }function run() public override { // Create and select the mainnet fork for proposal execution primaryForkId = vm.createFork("mainnet"); vm.selectFork(primaryForkId); uint256[] memory chainIds = new uint256[](1); chainIds[0] = 1; // Set the addresses object by reading addresses from the json file addresses = new Addresses( vm.envOr("ADDRESSES_PATH", string("./addresses")), chainIds ); // Set the timelock. This address is used for proposal simulation and checking on-chain proposal state setTimelock(addresses.getAddress("ARBITRUM_L1_TIMELOCK")); // Call the run function of the parent contract 'Proposal.sol' super.run(); }function simulate() public override { // Proposer must be the Arbitrum bridge address proposer = addresses.getAddress("ARBITRUM_BRIDGE"); // Executor can be anyone address executor = address(1); // Simulate the actions in the `build` function _simulateActions(proposer, executor); }function validate() public override { // Get proxy address IProxy proxy = IProxy( addresses.getAddress("ARBITRUM_L1_WETH_GATEWAY_PROXY") ); // Ensure implementation is upgraded to the newly deployed implementation require( proxy.implementation() == addresses.getAddress("ARBITRUM_L1_WETH_GATEWAY_IMPLEMENTATION"), "Proxy implementation not set" ); }
Running the Proposal
Last updated