Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Base Bundler #430

Merged
merged 51 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
4014e7e
feat: base bundler
MathisGD May 6, 2024
afad0b9
chore: readd removed files
MathisGD May 6, 2024
70c3052
chore: fix ci
MathisGD May 6, 2024
03c63b0
chore: improve ci names
MathisGD May 6, 2024
7a711c1
test: make tests pass
MathisGD May 7, 2024
72d6a3a
test: fix permit test
MathisGD May 7, 2024
22cc6d1
chore: rename ethereum folder fork
MathisGD May 7, 2024
73b4a60
test: remove ethereum test helper
MathisGD May 7, 2024
8d46f69
test: rename files
MathisGD May 7, 2024
613bddc
test: harmonization
MathisGD May 7, 2024
7bec750
chore: little fixes in the ci
MathisGD May 13, 2024
ccac0bf
test: remove mocks
MathisGD May 13, 2024
13c711f
test: fix wrong changes in refactor
MathisGD May 13, 2024
1e9b7d3
test: fix aave v3 test not working (dai not listed on base)
MathisGD May 13, 2024
2c982d4
chore: remove chain matrix for local tests
MathisGD May 13, 2024
86b7a5d
refactor: pass weth address as argument to have the same init bytecod…
MathisGD May 13, 2024
de336f3
test: fix tests on base
MathisGD May 13, 2024
ee89eba
Merge branch 'feat/base' into refactor/bytecode
MathisGD May 13, 2024
90aa49f
Merge branch 'feat/base' into test/refactor
MathisGD May 13, 2024
99cb382
style: rename base bundler
MathisGD May 13, 2024
7cc029a
test: rename baseTest
MathisGD May 13, 2024
46cc4c5
test: fix test on ethereum
MathisGD May 14, 2024
516a56d
Merge branch 'feat/base' into refactor/bytecode
MathisGD May 14, 2024
b9d5c80
Merge branch 'feat/base' into style/rootbundler
MathisGD May 14, 2024
ad02191
test: fix base test
MathisGD May 14, 2024
cf9bbdc
Merge branch 'feat/base' into style/rootbundler
MathisGD May 14, 2024
61cd8bb
Merge branch 'feat/base' into refactor/bytecode
MathisGD May 14, 2024
29b9b8b
Merge branch 'feat/base' into test/refactor
MathisGD May 14, 2024
0d9ad2a
Merge remote-tracking branch 'origin/test/refactor' into test/refactor
MathisGD May 14, 2024
5ec8016
test: docs
MathisGD May 14, 2024
21dace2
style: rename root => core
MathisGD May 14, 2024
38dd53f
chore: use relative path
MathisGD May 14, 2024
980905d
Merge pull request #434 from morpho-org/style/rootbundler
MathisGD May 14, 2024
cefa93d
Merge branch 'feat/base' into refactor/bytecode
MathisGD May 14, 2024
0b63fe5
Merge pull request #433 from morpho-org/refactor/bytecode
MathisGD May 14, 2024
d1e033b
test: one single mock
MathisGD May 14, 2024
ed250d5
Merge branch 'feat/base' into test/refactor
MathisGD May 14, 2024
534b13c
Merge branch 'main' into feat/base
MathisGD May 14, 2024
0268771
Merge remote-tracking branch 'origin/feat/base' into test/refactor
MathisGD May 14, 2024
dc0248c
test: rename files
MathisGD May 14, 2024
42a5e62
test: rename files
MathisGD May 14, 2024
703aac3
test: rename files
MathisGD May 14, 2024
3c545fb
Merge branch 'feat/base' into test/refactor
MathisGD May 14, 2024
5603f2a
test: fix renaming issues
MathisGD May 14, 2024
79da167
Merge branch 'feat/base' into test/refactor
MathisGD May 14, 2024
916df26
Merge pull request #432 from morpho-org/test/refactor
MathisGD May 14, 2024
bee2439
docs: document agnostic bunder
MathisGD May 14, 2024
3bec728
test: minor improvements
MathisGD May 14, 2024
3b916f6
test: minor improvements
MathisGD May 14, 2024
4b42813
test: run fork tests by default on Ethereum
MathisGD May 15, 2024
c5eeccf
docs: forge t --chain
MathisGD May 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .github/workflows/foundry.yml
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ jobs:
strategy:
fail-fast: true
matrix:
chain: [1, 8453]
type: ["slow", "fast"]
include:
- type: "slow"
Expand All @@ -101,8 +102,8 @@ jobs:

- uses: ./.github/actions/install-cache

- name: Run local tests in ${{ matrix.type }} mode
run: yarn test:forge:local
- name: Run local tests on chain ${{ matrix.chain }} in ${{ matrix.type }} mode
run: yarn test:forge:local --chain ${{ matrix.chain }}
env:
FOUNDRY_FUZZ_RUNS: ${{ matrix.fuzz-runs }}
FOUNDRY_FUZZ_MAX_TEST_REJECTS: ${{ matrix.max-test-rejects }}
Expand All @@ -117,6 +118,7 @@ jobs:
strategy:
fail-fast: true
matrix:
chain: [1, 8453]
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
type: ["slow", "fast"]
include:
- type: "slow"
Expand All @@ -142,8 +144,8 @@ jobs:

- uses: ./.github/actions/install-cache

- name: Run ethereum tests in ${{ matrix.type }} mode
run: yarn test:forge:ethereum
- name: Run fork tests on chain ${{ matrix.chain }} in ${{ matrix.type }} mode
run: yarn test:forge:ethereum --chain ${{ matrix.chain }}
env:
ALCHEMY_KEY: ${{ secrets.ALCHEMY_KEY }}
FOUNDRY_FUZZ_RUNS: ${{ matrix.fuzz-runs }}
Expand Down
33 changes: 25 additions & 8 deletions config/Configured.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {Config, ConfigMarket, ConfigLib} from "./ConfigLib.sol";

import {StdChains, VmSafe} from "../lib/forge-std/src/StdChains.sol";

import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";

abstract contract Configured is StdChains {
using ConfigLib for Config;

Expand All @@ -19,6 +21,10 @@ abstract contract Configured is StdChains {
address internal WBTC;
address internal WETH;
address internal WNATIVE;
address internal ST_ETH;
address internal WST_ETH;
address internal CB_ETH;
address internal S_DAI;
address[] internal allAssets;

address internal AAVE_V2_POOL;
Expand All @@ -32,29 +38,40 @@ abstract contract Configured is StdChains {

ConfigMarket[] internal configMarkets;

function _network() internal view virtual returns (string memory);
string internal network;

function _loadConfig() internal virtual {
if (block.chainid == 0) {
revert("chain id must be specified (`--chain <chainid>`)");
MerlinEgalite marked this conversation as resolved.
Show resolved Hide resolved
} else if (block.chainid == 1) {
network = "ethereum";
} else if (block.chainid == 8453) {
network = "base";
} else {
revert(string.concat("no config for chain ", Strings.toString(block.chainid)));
}

function _initConfig() internal returns (Config storage) {
// Fetch config.
if (bytes(CONFIG.json).length == 0) {
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/config/", _network(), ".json");
string memory path = string.concat(root, "/config/", network, ".json");

CONFIG.json = vm.readFile(path);
}

return CONFIG;
}

function _loadConfig() internal virtual {
DAI = CONFIG.getAddress("DAI");
USDC = CONFIG.getAddress("USDC");
USDT = CONFIG.getAddress("USDT");
LINK = CONFIG.getAddress("LINK");
WBTC = CONFIG.getAddress("WBTC");
WETH = CONFIG.getAddress("WETH");
WNATIVE = CONFIG.getWrappedNative();
ST_ETH = CONFIG.getAddress("stETH");
WST_ETH = CONFIG.getAddress("wstETH");
CB_ETH = CONFIG.getAddress("cbETH");
S_DAI = CONFIG.getAddress("sDai");

allAssets = [DAI, USDC, USDT, LINK, WBTC, WETH];
allAssets = [DAI, USDC, USDT, LINK, WBTC, WETH, ST_ETH, WST_ETH, CB_ETH, S_DAI];

ConfigMarket[] memory allConfigMarkets = CONFIG.getMarkets();
for (uint256 i; i < allConfigMarkets.length; ++i) {
Expand Down
33 changes: 0 additions & 33 deletions config/ConfiguredEthereum.sol

This file was deleted.

31 changes: 31 additions & 0 deletions config/base.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"chainId": 8453,
"forkBlockNumber": 14000000,
"markets": [
{
"loanToken": "WETH",
"collateralToken": "WETH",
"lltv": 800000000000000000
}
],
"DAI": "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
"USDC": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"LINK": "0xC9EbC2469E403DD89eAcA78C6B0b216fc7501011",
"WETH": "0x4200000000000000000000000000000000000006",
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
"wrappedNative": "WETH",
"aaveV3Pool": "0xA238Dd80C259a72e81d7e4664a9801593F98d1c5",
"cWETHv3": "0x46e6b214b524310239732D51387075E0e70970bf",
"cbETH": "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22",
"USDT": "0x0000000000000000000000000000000000000000",
"WBTC": "0x0000000000000000000000000000000000000000",
"stETH": "0x0000000000000000000000000000000000000000",
"wstETH": "0x0000000000000000000000000000000000000000",
"rETH": "0x0000000000000000000000000000000000000000",
"sDai": "0x0000000000000000000000000000000000000000",
"aaveV2Pool": "0x0000000000000000000000000000000000000000",
"aaveV3Optimizer": "0x0000000000000000000000000000000000000000",
"comptroller": "0x0000000000000000000000000000000000000000",
"cDAIv2": "0x0000000000000000000000000000000000000000",
"cETHv2": "0x0000000000000000000000000000000000000000",
"cUSDCv2": "0x0000000000000000000000000000000000000000"
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
}
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ runs = 16

[profile.default.rpc_endpoints]
ethereum = "https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}"
base = "https://base-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}"
tenderly = "https://rpc.tenderly.co/fork/${TENDERLY_FORK_ID}"

[profile.default.fmt]
Expand Down
38 changes: 38 additions & 0 deletions src/base/BaseBundlerV2.sol
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.24;

import {BaseLib} from "./libraries/BaseLib.sol";

import {BaseBundler} from "../BaseBundler.sol";
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
import {TransferBundler} from "../TransferBundler.sol";
import {Permit2Bundler} from "../Permit2Bundler.sol";
import {ERC4626Bundler} from "../ERC4626Bundler.sol";
import {WNativeBundler} from "../WNativeBundler.sol";
import {UrdBundler} from "../UrdBundler.sol";
import {MorphoBundler} from "../MorphoBundler.sol";
import {ERC20WrapperBundler} from "../ERC20WrapperBundler.sol";

/// @title BaseBundlerV2
/// @author Morpho Labs
/// @custom:contact security@morpho.org
/// @notice Bundler contract specific to Base.
contract BaseBundlerV2 is
TransferBundler,
Permit2Bundler,
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
ERC4626Bundler,
WNativeBundler,
UrdBundler,
MorphoBundler,
ERC20WrapperBundler
{
/* CONSTRUCTOR */

constructor(address morpho) WNativeBundler(BaseLib.WETH) MorphoBundler(morpho) {}
MathisGD marked this conversation as resolved.
Show resolved Hide resolved

/* INTERNAL */

/// @inheritdoc MorphoBundler
function _isSenderAuthorized() internal view override(BaseBundler, MorphoBundler) returns (bool) {
return MorphoBundler._isSenderAuthorized();
}
}
7 changes: 7 additions & 0 deletions src/base/libraries/BaseLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

library BaseLib {
/// @dev The address of the WETH contract on Base.
address internal constant WETH = 0x4200000000000000000000000000000000000006;
}
9 changes: 7 additions & 2 deletions test/forge/ethereum/EthereumBundlerEthereumTest.sol
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ pragma solidity ^0.8.0;

import {IAllowanceTransfer} from "../../../lib/permit2/src/interfaces/IAllowanceTransfer.sol";

import "../../../src/ethereum/EthereumBundlerV2.sol";
import {EthereumBundlerV2} from "../../../src/ethereum/EthereumBundlerV2.sol";
import {BaseBundlerV2} from "../../../src/base/BaseBundlerV2.sol";

import "./helpers/EthereumTest.sol";

Expand All @@ -17,7 +18,11 @@ contract EthereumBundlerEthereumTest is EthereumTest {
function setUp() public override {
super.setUp();

bundler = new EthereumBundlerV2(address(morpho));
if (block.chainid == 1) {
bundler = new EthereumBundlerV2(address(morpho));
} else if (block.chainid == 8453) {
bundler = new BaseBundlerV2(address(morpho));
}
MathisGD marked this conversation as resolved.
Show resolved Hide resolved

vm.prank(USER);
morpho.setAuthorization(address(bundler), true);
Expand Down
6 changes: 3 additions & 3 deletions test/forge/ethereum/EthereumPermitBundlerEthereumTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ contract EthereumPermitBundlerEthereumTest is EthereumTest {
bundler = new EthereumPermitBundlerMock();
}

function testPermitDai(uint256 privateKey, uint256 expiry) public {
function testPermitDai(uint256 privateKey, uint256 expiry) public onlyEthereum {
expiry = bound(expiry, block.timestamp, type(uint48).max);
privateKey = bound(privateKey, 1, type(uint160).max);

Expand All @@ -34,12 +34,12 @@ contract EthereumPermitBundlerEthereumTest is EthereumTest {
assertEq(ERC20(DAI).allowance(user, address(bundler)), type(uint256).max, "allowance(user, bundler)");
}

function testPermitDaiUninitiated() public {
function testPermitDaiUninitiated() public onlyEthereum {
vm.expectRevert(bytes(ErrorsLib.UNINITIATED));
EthereumPermitBundlerMock(address(bundler)).permitDai(0, SIGNATURE_DEADLINE, true, 0, 0, 0, true);
}

function testPermitDaiRevert(uint256 privateKey, uint256 expiry) public {
function testPermitDaiRevert(uint256 privateKey, uint256 expiry) public onlyEthereum {
expiry = bound(expiry, block.timestamp, type(uint48).max);
privateKey = bound(privateKey, 1, type(uint160).max);

Expand Down
18 changes: 10 additions & 8 deletions test/forge/ethereum/EthereumStEthBundlerEthereumTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,22 @@ contract EthereumStEthBundlerEthereumTest is EthereumTest {
using SafeTransferLib for ERC20;

function setUp() public override {
if (block.chainid != 1) return;

super.setUp();

bundler = new EthereumStEthBundlerMock();
}

function testStakeEthZeroAmount() public {
function testStakeEthZeroAmount() public onlyEthereum {
bundle.push(abi.encodeCall(StEthBundler.stakeEth, (0, 0, address(0))));

vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT));
vm.prank(USER);
bundler.multicall(bundle);
}

function testStakeEth(uint256 amount) public {
function testStakeEth(uint256 amount) public onlyEthereum {
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
amount = bound(amount, MIN_AMOUNT, 10_000 ether);

uint256 shares = IStEth(ST_ETH).getSharesByPooledEth(amount);
Expand All @@ -49,7 +51,7 @@ contract EthereumStEthBundlerEthereumTest is EthereumTest {
assertApproxEqAbs(ERC20(ST_ETH).balanceOf(RECEIVER), amount, 3, "balanceOf(RECEIVER)");
}

function testStakeEthSlippageAdapts(uint256 amount) public {
function testStakeEthSlippageAdapts(uint256 amount) public onlyEthereum {
amount = bound(amount, MIN_AMOUNT, 10_000 ether);

uint256 shares = IStEth(ST_ETH).getSharesByPooledEth(amount);
Expand All @@ -66,7 +68,7 @@ contract EthereumStEthBundlerEthereumTest is EthereumTest {
assertApproxEqAbs(IStEth(ST_ETH).sharesOf(USER), shares / 2, 2, "shares");
}

function testStakeEthSlippageExceeded(uint256 amount) public {
function testStakeEthSlippageExceeded(uint256 amount) public onlyEthereum {
amount = bound(amount, MIN_AMOUNT, 10_000 ether);

uint256 shares = IStEth(ST_ETH).getSharesByPooledEth(amount);
Expand All @@ -82,15 +84,15 @@ contract EthereumStEthBundlerEthereumTest is EthereumTest {
bundler.multicall{value: amount}(bundle);
}

function testWrapZeroAmount() public {
function testWrapZeroAmount() public onlyEthereum {
bundle.push(abi.encodeCall(StEthBundler.wrapStEth, (0)));

vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT));
vm.prank(USER);
bundler.multicall(bundle);
}

function testWrapStEth(uint256 privateKey, uint256 amount) public {
function testWrapStEth(uint256 privateKey, uint256 amount) public onlyEthereum {
address user;
(privateKey, user) = _boundPrivateKey(privateKey);
amount = bound(amount, MIN_AMOUNT, MAX_AMOUNT);
Expand Down Expand Up @@ -121,15 +123,15 @@ contract EthereumStEthBundlerEthereumTest is EthereumTest {
assertEq(ERC20(ST_ETH).balanceOf(RECEIVER), 0, "wstEth.balanceOf(RECEIVER)");
}

function testUnwrapZeroAmount() public {
function testUnwrapZeroAmount() public onlyEthereum {
bundle.push(_unwrapStEth(0));

vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT));
vm.prank(USER);
bundler.multicall(bundle);
}

function testUnwrapWstEth(uint256 privateKey, uint256 amount) public {
function testUnwrapWstEth(uint256 privateKey, uint256 amount) public onlyEthereum {
address user;
(privateKey, user) = _boundPrivateKey(privateKey);
amount = bound(amount, MIN_AMOUNT, MAX_AMOUNT);
Expand Down
13 changes: 5 additions & 8 deletions test/forge/ethereum/helpers/EthereumTest.sol
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import "../../../../config/ConfiguredEthereum.sol";
import "../../../../config/Configured.sol";

import "../../helpers/ForkTest.sol";

contract EthereumTest is ConfiguredEthereum, ForkTest {
function _network() internal view virtual override(Configured, ConfiguredEthereum) returns (string memory) {
return ConfiguredEthereum._network();
}

function _loadConfig() internal virtual override(Configured, ConfiguredEthereum) {
ConfiguredEthereum._loadConfig();
contract EthereumTest is Configured, ForkTest {
modifier onlyEthereum() {
vm.skip(block.chainid != 1);
_;
}

function deal(address asset, address recipient, uint256 amount) internal virtual override {
Expand Down
Loading
Loading