forked from aave-starknet-project/aave-starknet-bridge
-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP. Add Aave governance proposal payload (`AaveStarknetBridgeActivat…
…ionPayload`) (aave-starknet-project#128) * Added AaveStarknetBridgeActivationPayload. Pending tests * Added documentation on payload * Cover edge case of CREATE2 frontrunning on activation payload * - Added predictProxyAddress() to AaveStarknetBridgeActivationPayload - Fix on function visibility of AaveStarknetBridgeActivationPayload * test Aave activation payload * prepare l2 activation spell contract * add l1 bridge impl * declare spell contract * add script to deploy L1 gov payload --------- Co-authored-by: hsouf <[email protected]> Co-authored-by: Massil Achab <[email protected]>
- Loading branch information
1 parent
f79196f
commit 2020c17
Showing
9 changed files
with
703 additions
and
6 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
name: Test bridge activation | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
pull_request: | ||
|
||
env: | ||
ALCHEMY_KEY: ${{ secrets.ALCHEMY_KEY }} | ||
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }} | ||
ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }} | ||
BLOCK_NUMBER: "15982890" | ||
DAI_WHALE: "0xe78388b4ce79068e89bf8aa7f218ef6b9ab0e9d0" | ||
USDC_WHALE: "0x47ac0fb4f2d84898e4d9e7b4dab3c24507a6d503" | ||
STKAAVE_WHALE: "0x32b61bb22cbe4834bc3e73dce85280037d944a4d" | ||
EMISSION_MANAGER: "0xEE56e2B3D491590B5b31738cC34d5232F378a8D5" | ||
|
||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
tests: ["bridge_activation.test.ts"] | ||
python-version: ["3.9.0"] # Cairo was tested with this version | ||
node-version: ["16"] | ||
env: | ||
L2_NETWORK: "l2_testnet" | ||
steps: | ||
- uses: actions/checkout@v3 | ||
|
||
- name: Use Node.js | ||
uses: actions/setup-node@v3 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
cache: "yarn" | ||
|
||
- name: Setup Python | ||
uses: actions/setup-python@v3 | ||
with: | ||
python-version: ${{ matrix.python-version }} | ||
|
||
- name: Cache Python environment | ||
uses: actions/cache@v3 | ||
with: | ||
path: .venv | ||
key: venv-${{ runner.os }}-py${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }} | ||
|
||
- name: Install dependencies | ||
run: | | ||
python3 -m venv .venv | ||
source .venv/bin/activate | ||
yarn | ||
pip install poetry | ||
poetry install | ||
- name: Start the l2 & l1 test networks | ||
run: | | ||
yarn testnet:l2 & | ||
yarn testnet:l1 & | ||
- name: Compile Cairo | ||
run: | | ||
yarn compile:l2 | ||
- name: Run tests | ||
run: | | ||
yarn test test/${{ matrix.tests }} |
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,130 @@ | ||
// SPDX-License-Identifier: Apache-2.0. | ||
pragma solidity ^0.8.0; | ||
|
||
import {AaveGovernanceV2} from "@bgd-labs/aave-address-book/src/AaveGovernanceV2.sol"; | ||
import {ITransparentProxyFactory} from "./interfaces/IProxyFactory.sol"; | ||
import {IBridge} from "./interfaces/IBridge.sol"; | ||
import {ICrosschainForwarderStarknet} from "./interfaces/ICrosschainForwarderStarknet.sol"; | ||
|
||
/** | ||
* @title AaveStarknetBridgeActivationPayload | ||
* @author Aave on Starknet | ||
* @notice Aave governance proposal payload, activating the Aave <> Starknet Aave v2 Ethereum Bridge | ||
*/ | ||
contract AaveStarknetBridgeActivationPayload { | ||
address public constant STARKNET_MESSAGING_CORE = | ||
0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4; | ||
ICrosschainForwarderStarknet public constant CROSSCHAIN_FORWARDER_STARKNET = | ||
ICrosschainForwarderStarknet( | ||
0x8c598667A5a6A14F04172326e62CE143BF8edaAB | ||
); | ||
uint256 public constant L2_BRIDGE = | ||
0x0434ab0e4f2a743f871e4d57a16aef3df84c1a29b61565e016da91c1f824b021; | ||
address public constant INCENTIVES_CONTROLLER = | ||
0xd784927Ff2f95ba542BfC824c8a8a98F3495f6b5; | ||
ITransparentProxyFactory public constant PROXY_FACTORY = | ||
ITransparentProxyFactory(0xC354ce29aa85e864e55277eF47Fc6a92532Dd6Ca); | ||
string public constant ID_L1_BRIDGE = "aave_v2_ethereum.starknet_bridge"; | ||
|
||
IBridge public constant L1_BRIDGE_IMPLEMENTATION = | ||
IBridge(0x69F4057cC8A32bdE63c2d62724CE14Ed1aD4B93A); | ||
uint256 public constant L2_INIT_SPELL = | ||
0x00be3e7fe64939ef463bc80b76703b93c10a61944de34df5bb2dbc7b734e3159; | ||
|
||
function execute() external { | ||
( | ||
address[] memory l1Tokens, | ||
uint256[] memory l2Tokens, | ||
uint256[] memory ceilings | ||
) = getTokensData(); | ||
|
||
try | ||
/// @dev Using createDeterministic() because the spell on L2 side needs to know in advance the address | ||
/// of the proxy to be deployed | ||
PROXY_FACTORY.createDeterministic( | ||
address(L1_BRIDGE_IMPLEMENTATION), | ||
AaveGovernanceV2.SHORT_EXECUTOR, | ||
abi.encodeWithSelector( | ||
L1_BRIDGE_IMPLEMENTATION.initialize.selector, | ||
L2_BRIDGE, | ||
STARKNET_MESSAGING_CORE, | ||
INCENTIVES_CONTROLLER, | ||
l1Tokens, | ||
l2Tokens, | ||
ceilings | ||
), | ||
keccak256(abi.encode(ID_L1_BRIDGE)) | ||
) | ||
{} catch (bytes memory) { | ||
// Do nothing. If reverted, it is because the contract is already deployed | ||
// and initialized with exactly the parameters we require | ||
} | ||
|
||
// Send message to activate the L2 side of the system, by nested delegatecall to the forwarder | ||
(bool success, ) = address(CROSSCHAIN_FORWARDER_STARKNET).delegatecall( | ||
abi.encodeWithSelector( | ||
CROSSCHAIN_FORWARDER_STARKNET.execute.selector, | ||
L2_INIT_SPELL | ||
) | ||
); | ||
|
||
require(success, "CROSSCHAIN_FORWARDER_STARKNET_execute()"); | ||
} | ||
|
||
function predictProxyAddress() public view returns (address) { | ||
( | ||
address[] memory l1Tokens, | ||
uint256[] memory l2Tokens, | ||
uint256[] memory ceilings | ||
) = getTokensData(); | ||
|
||
return | ||
PROXY_FACTORY.predictCreateDeterministic( | ||
address(L1_BRIDGE_IMPLEMENTATION), | ||
AaveGovernanceV2.SHORT_EXECUTOR, | ||
abi.encodeWithSelector( | ||
L1_BRIDGE_IMPLEMENTATION.initialize.selector, | ||
L2_BRIDGE, | ||
STARKNET_MESSAGING_CORE, | ||
INCENTIVES_CONTROLLER, | ||
l1Tokens, | ||
l2Tokens, | ||
ceilings | ||
), | ||
keccak256(abi.encode(ID_L1_BRIDGE)) | ||
); | ||
} | ||
|
||
function getTokensData() | ||
public | ||
pure | ||
returns ( | ||
address[] memory, | ||
uint256[] memory, | ||
uint256[] memory | ||
) | ||
{ | ||
address[] memory l1Tokens = new address[](3); | ||
l1Tokens[0] = 0xBcca60bB61934080951369a648Fb03DF4F96263C; // aUSDC | ||
l1Tokens[1] = 0x3Ed3B47Dd13EC9a98b44e6204A523E766B225811; // aUSDT | ||
l1Tokens[2] = 0x028171bCA77440897B824Ca71D1c56caC55b68A3; // aDAI | ||
|
||
uint256[] memory l2Tokens = new uint256[](3); | ||
l2Tokens[ | ||
0 | ||
] = 0x014cdaa224881ea760b055a50b7b8e65447d9310f5c637294e08a0fc0d04c0ce; // static aUSDC | ||
l2Tokens[ | ||
1 | ||
] = 0x02e905e3d2fcf4e5813fef9bfe528a304e8e5adc8cbdc247b3980d7a96a01b90; // static aUSDT | ||
l2Tokens[ | ||
2 | ||
] = 0x04212f12efcfc9e847bd98e58daff7dc588c4896f6cd320b74023ad5606f02fd; // static aDAI | ||
|
||
uint256[] memory ceilings = new uint256[](3); | ||
ceilings[0] = 30_000_000000; // ceiling of aUSDC, 6 decimals | ||
ceilings[1] = 30_000_000000; // ceiling of aUSDT, 6 decimals | ||
ceilings[2] = 30_000 ether; // ceiling of aDAI, 18 decimals | ||
|
||
return (l1Tokens, l2Tokens, ceilings); | ||
} | ||
} |
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,6 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
interface ICrosschainForwarderStarknet { | ||
function execute(uint256 spell) external; | ||
} |
135 changes: 135 additions & 0 deletions
135
contracts/l1/mocks/MockAaveStarknetBridgeActivationPayload.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,135 @@ | ||
// SPDX-License-Identifier: Apache-2.0. | ||
pragma solidity ^0.8.0; | ||
|
||
import {ITransparentProxyFactory} from "../interfaces/IProxyFactory.sol"; | ||
import {IBridge} from "../interfaces/IBridge.sol"; | ||
import {ICrosschainForwarderStarknet} from "../interfaces/ICrosschainForwarderStarknet.sol"; | ||
|
||
contract MockAaveStarknetBridgeActivationPayload { | ||
address public immutable STARKNET_MESSAGING_CORE; | ||
address public immutable SHORT_EXECUTOR; | ||
ICrosschainForwarderStarknet public immutable CROSSCHAIN_FORWARDER_STARKNET; | ||
uint256 public immutable L2_BRIDGE; | ||
address public constant INCENTIVES_CONTROLLER = | ||
0xd784927Ff2f95ba542BfC824c8a8a98F3495f6b5; | ||
ITransparentProxyFactory public constant PROXY_FACTORY = | ||
ITransparentProxyFactory(0xC354ce29aa85e864e55277eF47Fc6a92532Dd6Ca); | ||
string public constant ID_L1_BRIDGE = "aave_v2_ethereum.starknet_bridge"; | ||
|
||
IBridge public immutable L1_BRIDGE_IMPLEMENTATION; // | ||
uint256 public constant L2_INIT_SPELL = 0; // | ||
|
||
constructor( | ||
address starknet, | ||
address starknetForwarder, | ||
address bridge, | ||
uint256 l2Bridge, | ||
address executor | ||
) { | ||
STARKNET_MESSAGING_CORE = starknet; | ||
CROSSCHAIN_FORWARDER_STARKNET = ICrosschainForwarderStarknet( | ||
starknetForwarder | ||
); | ||
|
||
L1_BRIDGE_IMPLEMENTATION = IBridge(bridge); | ||
L2_BRIDGE = l2Bridge; | ||
SHORT_EXECUTOR = executor; | ||
} | ||
|
||
//takes the mock spell as param, should be removed once spell contracts has been whitelisted | ||
function execute(uint256 spell) external { | ||
( | ||
address[] memory l1Tokens, | ||
uint256[] memory l2Tokens, | ||
uint256[] memory ceilings | ||
) = getTokensData(); | ||
|
||
try | ||
/// @dev Using createDeterministic() because the spell on L2 side needs to know in advance the address | ||
/// of the proxy to be deployed | ||
PROXY_FACTORY.createDeterministic( | ||
address(L1_BRIDGE_IMPLEMENTATION), | ||
SHORT_EXECUTOR, | ||
abi.encodeWithSelector( | ||
L1_BRIDGE_IMPLEMENTATION.initialize.selector, | ||
L2_BRIDGE, | ||
STARKNET_MESSAGING_CORE, | ||
INCENTIVES_CONTROLLER, | ||
l1Tokens, | ||
l2Tokens, | ||
ceilings | ||
), | ||
keccak256(abi.encode(ID_L1_BRIDGE)) | ||
) | ||
{} catch (bytes memory) { | ||
// Do nothing. If reverted, it is because the contract is already deployed | ||
// and initialized with exactly the parameters we require | ||
} | ||
|
||
// Send message to activate the L2 side of the system, by nested delegatecall to the forwarder | ||
(bool success, ) = address(CROSSCHAIN_FORWARDER_STARKNET).delegatecall( | ||
abi.encodeWithSelector( | ||
CROSSCHAIN_FORWARDER_STARKNET.execute.selector, | ||
spell | ||
) | ||
); | ||
|
||
require(success, "CROSSCHAIN_FORWARDER_STARKNET_execute()"); | ||
} | ||
|
||
function predictProxyAddress() public returns (address) { | ||
( | ||
address[] memory l1Tokens, | ||
uint256[] memory l2Tokens, | ||
uint256[] memory ceilings | ||
) = getTokensData(); | ||
|
||
return | ||
PROXY_FACTORY.predictCreateDeterministic( | ||
address(L1_BRIDGE_IMPLEMENTATION), | ||
SHORT_EXECUTOR, | ||
abi.encodeWithSelector( | ||
L1_BRIDGE_IMPLEMENTATION.initialize.selector, | ||
L2_BRIDGE, | ||
STARKNET_MESSAGING_CORE, | ||
INCENTIVES_CONTROLLER, | ||
l1Tokens, | ||
l2Tokens, | ||
ceilings | ||
), | ||
keccak256(abi.encode(ID_L1_BRIDGE)) | ||
); | ||
} | ||
|
||
function getTokensData() | ||
public | ||
returns ( | ||
address[] memory, | ||
uint256[] memory, | ||
uint256[] memory | ||
) | ||
{ | ||
address[] memory l1Tokens = new address[](3); | ||
l1Tokens[0] = 0xBcca60bB61934080951369a648Fb03DF4F96263C; // aUSDC | ||
l1Tokens[1] = 0x3Ed3B47Dd13EC9a98b44e6204A523E766B225811; // aUSDT | ||
l1Tokens[2] = 0x028171bCA77440897B824Ca71D1c56caC55b68A3; // aDAI | ||
|
||
uint256[] memory l2Tokens = new uint256[](3); | ||
l2Tokens[ | ||
0 | ||
] = 0x014cdaa224881ea760b055a50b7b8e65447d9310f5c637294e08a0fc0d04c0ce; // static aUSDC | ||
l2Tokens[ | ||
1 | ||
] = 0x02e905e3d2fcf4e5813fef9bfe528a304e8e5adc8cbdc247b3980d7a96a01b90; // static aUSDT | ||
l2Tokens[ | ||
2 | ||
] = 0x04212f12efcfc9e847bd98e58daff7dc588c4896f6cd320b74023ad5606f02fd; // static aDAI | ||
|
||
uint256[] memory ceilings = new uint256[](3); | ||
ceilings[0] = 30_000_000000; // ceiling of aUSDC, 6 decimals | ||
ceilings[1] = 30_000_000000; // ceiling of aUSDT, 6 decimals | ||
ceilings[2] = 30_000 ether; // ceiling of aDAI, 18 decimals | ||
|
||
return (l1Tokens, l2Tokens, ceilings); | ||
} | ||
} |
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
Oops, something went wrong.