This template contains an opinionated smart contract template for creating proposals to list assets on the aave v3 pools that are controlled by cross-chain governance.
To simplify the process of creating a cross-chain proposal this repository contains opinionated CrosschainForwarder
contracts for Polygon
, Optimism
and Arbitrum
abstracting away the complexity of bridging & cross-chain gas calculations.
All the forwarders follow the same pattern. They expect a payload to be deployed on L2 and to be executed with a parameterless execute()
signature and via DELEGATECALL
.
For a proposal to be executed on Polygon it needs to pass a mainnet governance proposal that sends an encoded payload via sendMessageToChild(address,bytes)
on FX_ROOT(mainnet) to FX_CHILD(Polygon).
Once the state is synced to FX_CHILD
on Polygon network it will queue the payload on POLYGON_BRIDGE_EXECUTOR.
For a proposal to be executed on Optimism it needs to pass a mainnet governance proposal that sends an encoded payload via sendMessage(address,bytes,uint32)
on L1_CROSS_DOMAIN_MESSENGER(mainnet) to L2_CROSS_DOMAIN_MESSENGER(Optimism).
Once the state is L2_CROSS_DOMAIN_MESSENGER
on Optimism it will queue the payload on OPTIMISM_BRIDGE_EXECUTOR.
For a proposal to be executed on Arbitrum it needs to pass a mainnet governance proposal that sends an encoded payload via unsafeCreateRetryableTicket{value: uint256}(address,uint256,uint256,address,address,uint256,uint256,bytes)
on INBOX(mainnet). The Arbitrum bridge will then call the bridged calldata via the L2_ALIAS of the mainnet msg.sender
(in this case is the aliased mainnet governance executor) which will queue the payload on ARBITRUM_BRIDGE_EXECUTOR.
Caveat: Opposed to the other bridges, Arbitrum inbox bridge requires you to supply some gas.
For simplicity the CrosschainForwarderArbitrum
expects some eth to be available on the SHORT_EXECUTOR.
You can check if you need to top-up the SHORT_EXECUTOR by calling getRequiredGas(580)
on the CrosschainForwarderArbitrum
.
cp .env.example .env
forge build
forge test
# Deploy proposal
make deploy-<mai|frax|op>
# Verify proposal
make verify-<mai|frax>
Make sure the referenced IPFS_HASH is properly encoded (check if the ipfs file is in json format and renders nicely on https://app.aave.com/governance/ipfs-preview/?ipfsHash=).
make deploy-l1-<mai|frax|op>-proposal
To create a proposal you have to do two things:
- deploy the Polygon Payload (see MiMatic)
- create the mainnet proposal (see DeployL1Proposal)
While the order of actions is important as the mainnet proposal needs the l2 payload address, both actions can be performed by different parties / addresses. The address creating the mainnet proposal requires 80k AAVE of proposition power.
- the deploy script on Polygon currently requires the --legacy flag due to issues with Polygon gas estimation ethers-io/ethers.js#2828 (comment)