Skip to content

Commit

Permalink
WIP. Add Aave governance proposal payload (`AaveStarknetBridgeActivat…
Browse files Browse the repository at this point in the history
…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
3 people authored Feb 2, 2023
1 parent f79196f commit 2020c17
Show file tree
Hide file tree
Showing 9 changed files with 703 additions and 6 deletions.
65 changes: 65 additions & 0 deletions .github/workflows/bridge-activation.yml
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 }}
130 changes: 130 additions & 0 deletions contracts/l1/AaveStarknetBridgeActivationPayload.sol
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);
}
}
6 changes: 6 additions & 0 deletions contracts/l1/interfaces/ICrosschainForwarderStarknet.sol
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 contracts/l1/mocks/MockAaveStarknetBridgeActivationPayload.sol
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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ namespace IBridge {
func delegate_execute{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() {

// bridge consts
const l2_bridge_address = 512643767668542850549097422634216397205258954717544946979257998691407990076;
const l1_bridge_address = 1034980665421734850219798662463523665156404235166;
const reward_token_address = 748385390664023138263219943884390301742053651531724542658262601656818474994;//rewAAVE
const l2_bridge_address = 1902308026103231708399763098802936489569449978602912766430085816491897565217;
const l1_bridge_address = 215523330021256381962255580076428681983938390349;
const reward_token_address = 2029792542476292482162717781560870950057314618366310397915647554677269565121;//rewAAVE
const aUSDC = 1077803441986936771120489637498156868855928333884;
const aDAI = 14304685556238090176394662515936233272922302627;
const aUSDT= 358678608052866257668291367909875857327283918865;
const staticV2EthADAI=3553586841338115378468599953580856750318258053701918475973449405835849242565;
const staticV2EthAUSDC=1877970670372008938438386847734197029013735878225782595520145731100643142366;
const staticV2EthAUSDT=1661137485454751519787291787981103293017576272529248260206323714387315909354;
const staticV2EthADAI=1867882240083208423799184639500919618573462941664712747609919667022414676733;
const staticV2EthAUSDC=588102177568622932536062234131824042711704376796923341979312819023177367758;
const staticV2EthAUSDT=1316341714119165292570263631681097098207593530730745197961203856625400552336;

// set reward token address on bridge
IBridge.set_reward_token(l2_bridge_address, reward_token_address);
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"dependencies": {
"@aave/core-v3": "^1.13.1",
"@aave/protocol-v2": "^1.0.1",
"@bgd-labs/aave-address-book": "1.3.0",
"@nomiclabs/hardhat-ethers": "^2.0.5",
"@nomiclabs/hardhat-waffle": "^2.0.3",
"@nomiclabs/hardhat-etherscan": "^3.1.0",
Expand Down
Loading

0 comments on commit 2020c17

Please sign in to comment.