-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: add forwarders * feat: bump address book
- Loading branch information
Showing
22 changed files
with
647 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule aave-address-book
updated
8 files
+1 −1 | scripts/config.ts | |
+1 −1 | src/AaveGovernanceV2.sol | |
+2 −2 | src/AaveV2Ethereum.sol | |
+1 −1 | src/AaveV2Polygon.sol | |
+13 −1 | src/AaveV3Ethereum.sol | |
+2 −2 | src/AaveV3Polygon.sol | |
+1 −1 | src/ts/AaveGovernanceV2.ts | |
+1 −1 | src/ts/AaveV3Ethereum.ts |
Submodule governance-crosschain-bridges
added at
32d66b
Submodule solidity-utils
updated
2 files
+16 −0 | Makefile | |
+1,136 −0 | src/contracts/oz-common/SafeCast.sol |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import './Utils.s.sol'; | ||
import {CrosschainForwarderPolygon} from '../src/crosschainforwarders/CrosschainForwarderPolygon.sol'; | ||
import {CrosschainForwarderOptimism} from '../src/crosschainforwarders/CrosschainForwarderOptimism.sol'; | ||
import {CrosschainForwarderArbitrum} from '../src/crosschainforwarders/CrosschainForwarderArbitrum.sol'; | ||
|
||
contract DeployPol is EthereumScript { | ||
function run() external broadcast { | ||
new CrosschainForwarderPolygon(); | ||
} | ||
} | ||
|
||
contract DeployOpt is EthereumScript { | ||
function run() external broadcast { | ||
new CrosschainForwarderOptimism(); | ||
} | ||
} | ||
|
||
contract DeployArb is EthereumScript { | ||
function run() external broadcast { | ||
new CrosschainForwarderArbitrum(); | ||
} | ||
} |
File renamed without changes.
File renamed without changes.
110 changes: 110 additions & 0 deletions
110
src/crosschainforwarders/CrosschainForwarderArbitrum.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import {AaveGovernanceV2} from 'aave-address-book/AaveGovernanceV2.sol'; | ||
import {AaveV3Arbitrum} from 'aave-address-book/AaveV3Arbitrum.sol'; | ||
import {IInbox} from 'governance-crosschain-bridges/contracts/dependencies/arbitrum/interfaces/IInbox.sol'; | ||
import {IL2BridgeExecutor} from 'governance-crosschain-bridges/contracts/interfaces/IL2BridgeExecutor.sol'; | ||
|
||
/** | ||
* @title A generic executor for proposals targeting the arbitrum v3 pool | ||
* @author BGD Labs | ||
* @notice You can **only** use this executor when the arbitrum payload has a `execute()` signature without parameters | ||
* @notice You can **only** use this executor when the arbitrum payload is expected to be executed via `DELEGATECALL` | ||
* @notice This contract assumes to be called via AAVE Governance V2 | ||
* @notice This contract will assume the SHORT_EXECUTOR will be topped up with enough funds to fund the short executor | ||
* @dev This executor is a generic wrapper to be used with Arbitrum Inbox (https://developer.offchainlabs.com/arbos/l1-to-l2-messaging) | ||
* It encodes a parameterless `execute()` with delegate calls and a specified target. | ||
* This encoded abi is then send to the Inbox to be synced executed on the arbitrum network. | ||
* Once synced the ARBITRUM_BRIDGE_EXECUTOR will queue the execution of the payload. | ||
*/ | ||
contract CrosschainForwarderArbitrum { | ||
IInbox public constant INBOX = IInbox(0x4Dbd4fc535Ac27206064B68FfCf827b0A60BAB3f); | ||
address public constant ARBITRUM_BRIDGE_EXECUTOR = AaveGovernanceV2.ARBITRUM_BRIDGE_EXECUTOR; | ||
address public constant ARBITRUM_GUARDIAN = 0xbbd9f90699c1FA0D7A65870D241DD1f1217c96Eb; | ||
|
||
// amount of gwei to overpay on basefee for fast submission | ||
uint256 public constant BASE_FEE_MARGIN = 10 gwei; | ||
|
||
/** | ||
* @dev calculateRetryableSubmissionFee on `0x00000000000000000000000000000000000000C8` for a queue call with 1 slot will yield a constant gasLimit of `429478` | ||
* To account for some margin we rounded up to 450000 | ||
*/ | ||
uint256 public constant L2_GAS_LIMIT = 450000; | ||
|
||
/** | ||
* @dev There is currently no oracle on L1 exposing gasPrice of arbitrum. Therefore we overpay by assuming 1 gwei (10x of current price). | ||
*/ | ||
uint256 public constant L2_MAX_FEE_PER_GAS = 1 gwei; | ||
|
||
/** | ||
* @dev returns the amount of gas needed for submitting the ticket | ||
* @param bytesLength the payload bytes length (usually 580) | ||
* @return uint256 maxSubmissionFee needed on L2 with BASE_FEE_MARGIN | ||
* @return uint256 estimated L2 redepmption fee | ||
*/ | ||
function getRequiredGas(uint256 bytesLength) public view returns (uint256, uint256) { | ||
return ( | ||
INBOX.calculateRetryableSubmissionFee(bytesLength, block.basefee + BASE_FEE_MARGIN), | ||
L2_GAS_LIMIT * L2_MAX_FEE_PER_GAS | ||
); | ||
} | ||
|
||
/** | ||
* @dev checks if the short executor is topped up with enough eth for proposal execution | ||
* with current basefee | ||
* @param bytesLength the payload bytes length (usually 580) | ||
* @return bool indicating if the SHORT_EXECUTOR has sufficient funds | ||
* @return uint256 the gas required for ticket creation and redemption | ||
*/ | ||
function hasSufficientGasForExecution(uint256 bytesLength) public view returns (bool, uint256) { | ||
(uint256 maxSubmission, uint256 maxRedemption) = getRequiredGas(bytesLength); | ||
uint256 requiredGas = maxSubmission + maxRedemption; | ||
return (AaveGovernanceV2.SHORT_EXECUTOR.balance >= requiredGas, requiredGas); | ||
} | ||
|
||
/** | ||
* @dev encodes the queue call which is forwarded to arbitrum | ||
* @param l2PayloadContract the address of the arbitrum payload | ||
*/ | ||
function getEncodedPayload(address l2PayloadContract) public pure returns (bytes memory) { | ||
address[] memory targets = new address[](1); | ||
targets[0] = l2PayloadContract; | ||
uint256[] memory values = new uint256[](1); | ||
values[0] = 0; | ||
string[] memory signatures = new string[](1); | ||
signatures[0] = 'execute()'; | ||
bytes[] memory calldatas = new bytes[](1); | ||
calldatas[0] = ''; | ||
bool[] memory withDelegatecalls = new bool[](1); | ||
withDelegatecalls[0] = true; | ||
return | ||
abi.encodeWithSelector( | ||
IL2BridgeExecutor.queue.selector, | ||
targets, | ||
values, | ||
signatures, | ||
calldatas, | ||
withDelegatecalls | ||
); | ||
} | ||
|
||
/** | ||
* @dev this function will be executed once the proposal passes the mainnet vote. | ||
* @param l2PayloadContract the arbitrum contract containing the `execute()` signature. | ||
*/ | ||
function execute(address l2PayloadContract) public { | ||
bytes memory queue = getEncodedPayload(l2PayloadContract); | ||
(uint256 maxSubmission, uint256 maxRedemption) = getRequiredGas(queue.length); | ||
INBOX.unsafeCreateRetryableTicket{value: maxSubmission + maxRedemption}( | ||
ARBITRUM_BRIDGE_EXECUTOR, | ||
0, // l2CallValue | ||
maxSubmission, // maxSubmissionCost | ||
address(ARBITRUM_BRIDGE_EXECUTOR), // excessFeeRefundAddress | ||
address(ARBITRUM_GUARDIAN), // callValueRefundAddress | ||
L2_GAS_LIMIT, // gasLimit | ||
L2_MAX_FEE_PER_GAS, // maxFeePerGas | ||
queue | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import {ICrossDomainMessenger} from 'governance-crosschain-bridges/contracts/dependencies/optimism/interfaces/ICrossDomainMessenger.sol'; | ||
import {IL2BridgeExecutor} from 'governance-crosschain-bridges/contracts/interfaces/IL2BridgeExecutor.sol'; | ||
|
||
interface ICanonicalTransactionChain { | ||
function enqueueL2GasPrepaid() external view returns (uint256); | ||
} | ||
|
||
/** | ||
* @title A generic executor for proposals targeting the optimism v3 pool | ||
* @author BGD Labs | ||
* @notice You can **only** use this executor when the optimism payload has a `execute()` signature without parameters | ||
* @notice You can **only** use this executor when the optimism payload is expected to be executed via `DELEGATECALL` | ||
* @notice You can **only** execute payloads on optimism with up to prepayed gas which is specified in `enqueueL2GasPrepaid` gas. | ||
* Prepaid gas is the maximum gas covered by the bridge without additional payment. | ||
* @dev This executor is a generic wrapper to be used with Optimism CrossDomainMessenger (https://etherscan.io/address/0x25ace71c97b33cc4729cf772ae268934f7ab5fa1) | ||
* It encodes and sends via the L2CrossDomainMessenger a message to queue for execution an action on L2, in the Aave OPTIMISM_BRIDGE_EXECUTOR. | ||
*/ | ||
contract CrosschainForwarderOptimism { | ||
/** | ||
* @dev The L1 Cross Domain Messenger contract sends messages from L1 to L2, and relays messages | ||
* from L2 onto L1. In this contract it's used by the governance SHORT_EXECUTOR to send the encoded L2 queuing over the bridge. | ||
*/ | ||
address public constant L1_CROSS_DOMAIN_MESSENGER_ADDRESS = | ||
0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1; | ||
|
||
/** | ||
* @dev The optimism bridge executor is a L2 governance execution contract. | ||
* This contract allows queuing of proposals by allow listed addresses (in this case the L1 short executor). | ||
* https://optimistic.etherscan.io/address/0x7d9103572bE58FfE99dc390E8246f02dcAe6f611 | ||
*/ | ||
address public constant OPTIMISM_BRIDGE_EXECUTOR = 0x7d9103572bE58FfE99dc390E8246f02dcAe6f611; | ||
|
||
/** | ||
* @dev The CTC contract is an append only log of transactions which must be applied to the rollup state. | ||
* It also holds configurations like the currently prepayed amount of gas which is what this contract is utilizing. | ||
* https://etherscan.io/address/0x5e4e65926ba27467555eb562121fac00d24e9dd2#code | ||
*/ | ||
ICanonicalTransactionChain public constant CANONICAL_TRANSACTION_CHAIN = | ||
ICanonicalTransactionChain(0x5E4e65926BA27467555EB562121fac00D24E9dD2); | ||
|
||
/** | ||
* @dev this function will be executed once the proposal passes the mainnet vote. | ||
* @param l2PayloadContract the optimism contract containing the `execute()` signature. | ||
*/ | ||
function execute(address l2PayloadContract) public { | ||
address[] memory targets = new address[](1); | ||
targets[0] = l2PayloadContract; | ||
uint256[] memory values = new uint256[](1); | ||
values[0] = 0; | ||
string[] memory signatures = new string[](1); | ||
signatures[0] = 'execute()'; | ||
bytes[] memory calldatas = new bytes[](1); | ||
calldatas[0] = ''; | ||
bool[] memory withDelegatecalls = new bool[](1); | ||
withDelegatecalls[0] = true; | ||
|
||
bytes memory queue = abi.encodeWithSelector( | ||
IL2BridgeExecutor.queue.selector, | ||
targets, | ||
values, | ||
signatures, | ||
calldatas, | ||
withDelegatecalls | ||
); | ||
ICrossDomainMessenger(L1_CROSS_DOMAIN_MESSENGER_ADDRESS).sendMessage( | ||
OPTIMISM_BRIDGE_EXECUTOR, | ||
queue, | ||
uint32(CANONICAL_TRANSACTION_CHAIN.enqueueL2GasPrepaid()) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import {IFxStateSender} from 'governance-crosschain-bridges/contracts/dependencies/polygon/fxportal/FxRoot.sol'; | ||
|
||
/** | ||
* @title A generic executor for proposals targeting the polygon v3 pool | ||
* @author BGD Labs | ||
* @notice You can **only** use this executor when the polygon payload has a `execute()` signature without parameters | ||
* @notice You can **only** use this executor when the polygon payload is expected to be executed via `DELEGATECALL` | ||
* @dev This executor is a generic wrapper to be used with FX bridges (https://github.com/fx-portal/contracts) | ||
* It encodes a parameterless `execute()` with delegate calls and a specified target. | ||
* This encoded abi is then send to the FX-root to be synced to the FX-child on the polygon network. | ||
* Once synced the POLYGON_BRIDGE_EXECUTOR will queue the execution of the payload. | ||
*/ | ||
contract CrosschainForwarderPolygon { | ||
address public constant FX_ROOT_ADDRESS = 0xfe5e5D361b2ad62c541bAb87C45a0B9B018389a2; | ||
address public constant POLYGON_BRIDGE_EXECUTOR = 0xdc9A35B16DB4e126cFeDC41322b3a36454B1F772; | ||
|
||
/** | ||
* @dev this function will be executed once the proposal passes the mainnet vote. | ||
* @param l2PayloadContract the polygon contract containing the `execute()` signature. | ||
*/ | ||
function execute(address l2PayloadContract) public { | ||
address[] memory targets = new address[](1); | ||
targets[0] = l2PayloadContract; | ||
uint256[] memory values = new uint256[](1); | ||
values[0] = 0; | ||
string[] memory signatures = new string[](1); | ||
signatures[0] = 'execute()'; | ||
bytes[] memory calldatas = new bytes[](1); | ||
calldatas[0] = ''; | ||
bool[] memory withDelegatecalls = new bool[](1); | ||
withDelegatecalls[0] = true; | ||
|
||
bytes memory actions = abi.encode(targets, values, signatures, calldatas, withDelegatecalls); | ||
IFxStateSender(FX_ROOT_ADDRESS).sendMessageToChild(POLYGON_BRIDGE_EXECUTOR, actions); | ||
} | ||
} |
Oops, something went wrong.