Arbitrum Timelock
Overview
This example showcases how FPS can be utilized for simulating proposals for the Arbitrum timelock on mainnet. Specifically, it upgrades the WETH gateway on L1. The proposal involves deploying a new implementation contract ARBITRUM_L1_WETH_GATEWAY_IMPLEMENTATION
and a governance action contract ARBITRUM_GAC_UPGRADE_WETH_GATEWAY
. Then, the timelock employs upgradeExecutor
to upgrade the WETH gateway. The proposer for the L1 timelock should always be the Arbitrum bridge.
The relevant contract can be found in the mocks folder.
Let's review each of the overridden functions:
name()
: Defines the name of the proposal.description()
: Provides a detailed description of the proposal.deploy()
: This function demonstrates the deployment of a new MockUpgrade, which will be used as the new implementation for the WETH Gateway Proxy and a new GAC contract for the upgrade.preBuildMock()
: Post-deployment mock actions, such as setting a newoutBox
forArbitrum bridge
usingvm.store
foundry cheatcode.build()
: Add actions to the proposal contract. In this example,ARBITRUM_L1_WETH_GATEWAY_PROXY
is upgraded to the new implementation. The actions should be written in solidity code and in the order they should be executed. Any calls (except to the Addresses object) will be recorded and stored as actions to execute in the run function. Thecaller
address is passed intobuildModifier
; it will call the actions inbuild
. The caller is the Arbitrum timelock in this example. ThebuildModifier
is a necessary modifier for thebuild
function and will not work without it. For further reading, see the build function.run()
: Sets up the environment for running the proposal, and executes all proposal actions. This setsaddresses
,primaryForkId
, andtimelock
and callssuper.run()
to run the entire proposal. In this example,primaryForkId
is set tomainnet
and the fork for running the proposal is selected. Next, theaddresses
object is set by reading the JSON file. The timelock contract to test is set usingsetTimelock
. This will be used to check onchain calldata and simulate the proposal. For further reading, see the run function.simulate()
: Executes the proposal actions outlined in thebuild()
step. This function performs a call to_simulateActions
from the inheritedTimelockProposal
contract. Internally,_simulateActions()
simulates a call to Timelock scheduleBatch and executeBatch with the calldata generated from the actions set up in the build step.validate()
: Validates that the implementation is upgraded correctly.
Running the Proposal
All required addresses should be in the JSON file, including DEPLOYER_EOA
address, which will deploy the new contracts. If these do not align, the script execution will fail.
The script will output the following:
It is crucial to note that two new addresses have been added to the Addresses.sol
storage. These addresses are not included in the JSON files when proposal is run without the DO_UPDATE_ADDRESS_JSON
flag set to true.
Last updated