diff --git a/.github/workflows/foundry.yml b/.github/workflows/foundry.yml index 60141493..05571cba 100644 --- a/.github/workflows/foundry.yml +++ b/.github/workflows/foundry.yml @@ -104,22 +104,23 @@ jobs: - uses: ./.github/actions/install-cache - - name: Run local tests in ${{ matrix.type }} mode + - name: Run local tests on chain ${{ matrix.chain }} in ${{ matrix.type }} mode run: yarn test:forge:local env: FOUNDRY_FUZZ_RUNS: ${{ matrix.fuzz-runs }} FOUNDRY_FUZZ_MAX_TEST_REJECTS: ${{ matrix.max-test-rejects }} FOUNDRY_FUZZ_SEED: 0x${{ github.event.pull_request.base.sha || github.sha }} - test-ethereum: + test-fork: needs: build-no-ir - name: Ethereum tests + name: Fork tests (chainid=${{ matrix.chain }}) runs-on: ubuntu-latest strategy: fail-fast: true matrix: + chain: [1, 8453] type: ["slow", "fast"] include: - type: "slow" @@ -145,8 +146,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:fork --chain ${{ matrix.chain }} env: ALCHEMY_KEY: ${{ secrets.ALCHEMY_KEY }} FOUNDRY_FUZZ_RUNS: ${{ matrix.fuzz-runs }} diff --git a/README.md b/README.md index 7887ea4e..ef0d79ca 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ![image (4)](https://github.com/morpho-org/morpho-blue-bundlers/assets/44097430/5cb0796b-c20c-415e-840d-8b0705836dc8) -Each Bundler is a domain-specific abstract layer of contract that implements some functions that can be bundled in a single call by EOAs to a single contract. They all inherit from [`BaseBundler`](./src/BaseBundler.sol) that enables bundling multiple function calls into a single `multicall(bytes[] calldata data)` call to the end bundler contract. Each chain-specific bundler is available under their chain-specific folder (e.g. [`ethereum`](./src/ethereum/)). +Each Bundler is a domain-specific abstract layer of contract that implements some functions that can be bundled in a single call by EOAs to a single contract. They all inherit from [`CoreBundler`](./src/CoreBundler.sol) that enables bundling multiple function calls into a single `multicall(bytes[] calldata data)` call to the end bundler contract. Each chain-specific bundler is available under their chain-specific folder (e.g. [`ethereum`](./src/ethereum/)). Some chain-specific domains are also scoped to the chain-specific folder, because they are not expected to be used on any other chain (e.g. DAI and its specific `permit` function is only available on Ethereum - see [`EthereumPermitBundler`](./src/ethereum/EthereumPermitBundler.sol)). @@ -16,7 +16,7 @@ User-end bundlers are provided in each chain-specific folder, instanciating all Install dependencies with `yarn`. -Run tests with `yarn test:forge`. +Run tests with `yarn test:forge --chain ` (chainid can be 1 or 8453). Note that the `EthereumBundlerV2` has been deployed with 80 000 optimizer runs. To compile contracts with the same configuration, run `FOUNDRY_PROFILE=ethereumBundlerV2 forge b`. diff --git a/config/Configured.sol b/config/Configured.sol index deaa03fc..f5cade8e 100644 --- a/config/Configured.sol +++ b/config/Configured.sol @@ -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; @@ -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; @@ -32,20 +38,27 @@ 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 `)"); + } 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"); @@ -53,8 +66,12 @@ abstract contract Configured is StdChains { 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) { diff --git a/config/ConfiguredEthereum.sol b/config/ConfiguredEthereum.sol deleted file mode 100644 index 58e5a7c4..00000000 --- a/config/ConfiguredEthereum.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -import "./Configured.sol"; - -abstract contract ConfiguredEthereum is Configured { - using ConfigLib for Config; - - address internal ST_ETH; - address internal WST_ETH; - address internal CB_ETH; - address internal S_DAI; - address[] internal allEthereumMainnetAssets; - - function _network() internal view virtual override returns (string memory) { - return "ethereum"; - } - - function _loadConfig() internal virtual override { - super._loadConfig(); - - ST_ETH = CONFIG.getAddress("stETH"); - WST_ETH = CONFIG.getAddress("wstETH"); - CB_ETH = CONFIG.getAddress("cbETH"); - S_DAI = CONFIG.getAddress("sDai"); - - allEthereumMainnetAssets = [ST_ETH, WST_ETH, CB_ETH, S_DAI]; - - for (uint256 i; i < allEthereumMainnetAssets.length; ++i) { - allAssets.push(allEthereumMainnetAssets[i]); - } - } -} diff --git a/config/base.json b/config/base.json new file mode 100644 index 00000000..5899f71e --- /dev/null +++ b/config/base.json @@ -0,0 +1,31 @@ +{ + "chainId": 8453, + "forkBlockNumber": 14000000, + "markets": [ + { + "loanToken": "WETH", + "collateralToken": "WETH", + "lltv": 800000000000000000 + } + ], + "DAI": "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb", + "USDC": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "LINK": "0xC9EbC2469E403DD89eAcA78C6B0b216fc7501011", + "WETH": "0x4200000000000000000000000000000000000006", + "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" +} diff --git a/foundry.toml b/foundry.toml index 87dfc186..011ea4f7 100644 --- a/foundry.toml +++ b/foundry.toml @@ -18,6 +18,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}" diff --git a/package.json b/package.json index 2eff5a25..c0be05cb 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "typecheck": "tsc --noEmit", "test:forge": "FOUNDRY_PROFILE=test forge test", "test:forge:local": "FOUNDRY_MATCH_CONTRACT=LocalTest yarn test:forge", - "test:forge:ethereum": "FOUNDRY_MATCH_CONTRACT=EthereumTest yarn test:forge", + "test:forge:fork": "FOUNDRY_MATCH_CONTRACT=ForkTest yarn test:forge", "test:hardhat": "hardhat test", "lint": "yarn lint:forge && yarn lint:ts", "lint:ts": "prettier --check pkg", diff --git a/src/BaseBundler.sol b/src/CoreBundler.sol similarity index 98% rename from src/BaseBundler.sol rename to src/CoreBundler.sol index e21231ec..a5493b3e 100644 --- a/src/BaseBundler.sol +++ b/src/CoreBundler.sol @@ -7,7 +7,7 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; import {UNSET_INITIATOR} from "./libraries/ConstantsLib.sol"; import {SafeTransferLib, ERC20} from "../lib/solmate/src/utils/SafeTransferLib.sol"; -/// @title BaseBundler +/// @title CoreBundler /// @author Morpho Labs /// @custom:contact security@morpho.org /// @notice Enables calling multiple functions in a single call to the same contract (self). @@ -15,7 +15,7 @@ import {SafeTransferLib, ERC20} from "../lib/solmate/src/utils/SafeTransferLib.s /// @dev Every bundler inheriting from this contract must have their external functions payable as they will be /// delegate called by the `multicall` function (which is payable, and thus might pass a non-null ETH value). It is /// recommended not to rely on `msg.value` as the same value can be reused for multiple calls. -abstract contract BaseBundler is IMulticall { +abstract contract CoreBundler is IMulticall { using SafeTransferLib for ERC20; /* STORAGE */ diff --git a/src/ERC20WrapperBundler.sol b/src/ERC20WrapperBundler.sol index da839e4d..d173e19b 100644 --- a/src/ERC20WrapperBundler.sol +++ b/src/ERC20WrapperBundler.sol @@ -5,7 +5,7 @@ import {ErrorsLib} from "./libraries/ErrorsLib.sol"; import {Math} from "../lib/morpho-utils/src/math/Math.sol"; import {SafeTransferLib, ERC20} from "../lib/solmate/src/utils/SafeTransferLib.sol"; -import {BaseBundler} from "./BaseBundler.sol"; +import {CoreBundler} from "./CoreBundler.sol"; import {ERC20Wrapper} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Wrapper.sol"; /// @title ERC20WrapperBundler @@ -14,7 +14,7 @@ import {ERC20Wrapper} from "../lib/openzeppelin-contracts/contracts/token/ERC20/ /// @notice Enables the wrapping and unwrapping of ERC20 tokens. The largest usecase is to wrap permissionless tokens to /// their permissioned counterparts and access permissioned markets on Morpho Blue. Permissioned tokens can be built /// using: https://github.com/morpho-org/erc20-permissioned -abstract contract ERC20WrapperBundler is BaseBundler { +abstract contract ERC20WrapperBundler is CoreBundler { using SafeTransferLib for ERC20; /* WRAPPER ACTIONS */ diff --git a/src/ERC4626Bundler.sol b/src/ERC4626Bundler.sol index c61651b7..51d57fe5 100644 --- a/src/ERC4626Bundler.sol +++ b/src/ERC4626Bundler.sol @@ -7,13 +7,13 @@ import {Math} from "../lib/morpho-utils/src/math/Math.sol"; import {ErrorsLib} from "./libraries/ErrorsLib.sol"; import {SafeTransferLib, ERC20} from "../lib/solmate/src/utils/SafeTransferLib.sol"; -import {BaseBundler} from "./BaseBundler.sol"; +import {CoreBundler} from "./CoreBundler.sol"; /// @title ERC4626Bundler /// @author Morpho Labs /// @custom:contact security@morpho.org /// @notice Bundler contract managing interactions with ERC4626 compliant tokens. -abstract contract ERC4626Bundler is BaseBundler { +abstract contract ERC4626Bundler is CoreBundler { using SafeTransferLib for ERC20; /* ACTIONS */ diff --git a/src/MorphoBundler.sol b/src/MorphoBundler.sol index c223e7ee..5dff3e9d 100644 --- a/src/MorphoBundler.sol +++ b/src/MorphoBundler.sol @@ -8,13 +8,13 @@ import {MarketParams, Signature, Authorization, IMorpho} from "../lib/morpho-blu import {ErrorsLib} from "./libraries/ErrorsLib.sol"; import {SafeTransferLib, ERC20} from "../lib/solmate/src/utils/SafeTransferLib.sol"; -import {BaseBundler} from "./BaseBundler.sol"; +import {CoreBundler} from "./CoreBundler.sol"; /// @title MorphoBundler /// @author Morpho Labs /// @custom:contact security@morpho.org /// @notice Bundler contract managing interactions with Morpho. -abstract contract MorphoBundler is BaseBundler, IMorphoBundler { +abstract contract MorphoBundler is CoreBundler, IMorphoBundler { using SafeTransferLib for ERC20; /* IMMUTABLES */ @@ -264,7 +264,7 @@ abstract contract MorphoBundler is BaseBundler, IMorphoBundler { _multicall(abi.decode(data, (bytes[]))); } - /// @inheritdoc BaseBundler + /// @inheritdoc CoreBundler function _isSenderAuthorized() internal view virtual override returns (bool) { return super._isSenderAuthorized() || msg.sender == address(MORPHO); } diff --git a/src/Permit2Bundler.sol b/src/Permit2Bundler.sol index 5dde2030..a33ef04e 100644 --- a/src/Permit2Bundler.sol +++ b/src/Permit2Bundler.sol @@ -9,13 +9,13 @@ import {Permit2Lib} from "../lib/permit2/src/libraries/Permit2Lib.sol"; import {SafeCast160} from "../lib/permit2/src/libraries/SafeCast160.sol"; import {ERC20} from "../lib/solmate/src/tokens/ERC20.sol"; -import {BaseBundler} from "./BaseBundler.sol"; +import {CoreBundler} from "./CoreBundler.sol"; /// @title Permit2Bundler /// @author Morpho Labs /// @custom:contact security@morpho.xyz /// @notice Bundler contract managing interactions with Uniswap's Permit2. -abstract contract Permit2Bundler is BaseBundler { +abstract contract Permit2Bundler is CoreBundler { using SafeCast160 for uint256; /* ACTIONS */ diff --git a/src/PermitBundler.sol b/src/PermitBundler.sol index bc74c7e9..b667e29c 100644 --- a/src/PermitBundler.sol +++ b/src/PermitBundler.sol @@ -3,13 +3,13 @@ pragma solidity 0.8.24; import {IERC20Permit} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; -import {BaseBundler} from "./BaseBundler.sol"; +import {CoreBundler} from "./CoreBundler.sol"; /// @title PermitBundler /// @author Morpho Labs /// @custom:contact security@morpho.xyz /// @notice Bundler contract managing interactions with tokens implementing EIP-2612. -abstract contract PermitBundler is BaseBundler { +abstract contract PermitBundler is CoreBundler { /// @notice Permits the given `amount` of `asset` from sender to be spent by the bundler via EIP-2612 Permit with /// the given `deadline` & EIP-712 signature's `v`, `r` & `s`. /// @param asset The address of the token to be permitted. diff --git a/src/StEthBundler.sol b/src/StEthBundler.sol index ecd04fd4..16a8f69b 100644 --- a/src/StEthBundler.sol +++ b/src/StEthBundler.sol @@ -8,13 +8,13 @@ import {Math} from "../lib/morpho-utils/src/math/Math.sol"; import {ErrorsLib} from "./libraries/ErrorsLib.sol"; import {SafeTransferLib, ERC20} from "../lib/solmate/src/utils/SafeTransferLib.sol"; -import {BaseBundler} from "./BaseBundler.sol"; +import {CoreBundler} from "./CoreBundler.sol"; /// @title StEthBundler /// @author Morpho Labs /// @custom:contact security@morpho.org /// @notice Contract allowing to bundle multiple interactions with stETH together. -abstract contract StEthBundler is BaseBundler { +abstract contract StEthBundler is CoreBundler { using SafeTransferLib for ERC20; /* IMMUTABLES */ diff --git a/src/TransferBundler.sol b/src/TransferBundler.sol index 6fac0c2c..30c559df 100644 --- a/src/TransferBundler.sol +++ b/src/TransferBundler.sol @@ -5,14 +5,14 @@ import {Math} from "../lib/morpho-utils/src/math/Math.sol"; import {ErrorsLib} from "./libraries/ErrorsLib.sol"; import {SafeTransferLib, ERC20} from "../lib/solmate/src/utils/SafeTransferLib.sol"; -import {BaseBundler} from "./BaseBundler.sol"; +import {CoreBundler} from "./CoreBundler.sol"; /// @title TransferBundler /// @author Morpho Labs /// @custom:contact security@morpho.org /// @notice Enables transfer of ERC20 and native tokens. /// @dev Assumes that any tokens left on the contract can be seized by anyone. -abstract contract TransferBundler is BaseBundler { +abstract contract TransferBundler is CoreBundler { using SafeTransferLib for ERC20; /* TRANSFER ACTIONS */ diff --git a/src/UrdBundler.sol b/src/UrdBundler.sol index 5e9ddaf3..994411ea 100644 --- a/src/UrdBundler.sol +++ b/src/UrdBundler.sol @@ -6,13 +6,13 @@ import {IUniversalRewardsDistributor} from import {ErrorsLib} from "./libraries/ErrorsLib.sol"; -import {BaseBundler} from "./BaseBundler.sol"; +import {CoreBundler} from "./CoreBundler.sol"; /// @title UrdBundler /// @author Morpho Labs /// @custom:contact security@morpho.xyz /// @notice Bundler that allows to claim token rewards on the Universal Rewards Distributor. -abstract contract UrdBundler is BaseBundler { +abstract contract UrdBundler is CoreBundler { /// @notice Claims `amount` of `reward` on behalf of `account` on the given rewards distributor, using `proof`. /// @dev Assumes the given distributor implements IUniversalRewardsDistributor. /// @param distributor The address of the reward distributor contract. diff --git a/src/WNativeBundler.sol b/src/WNativeBundler.sol index 840065cd..d4dab8bb 100644 --- a/src/WNativeBundler.sol +++ b/src/WNativeBundler.sol @@ -7,14 +7,14 @@ import {Math} from "../lib/morpho-utils/src/math/Math.sol"; import {ErrorsLib} from "./libraries/ErrorsLib.sol"; import {SafeTransferLib, ERC20} from "../lib/solmate/src/utils/SafeTransferLib.sol"; -import {BaseBundler} from "./BaseBundler.sol"; +import {CoreBundler} from "./CoreBundler.sol"; /// @title WNativeBundler /// @author Morpho Labs /// @custom:contact security@morpho.org /// @notice Bundler contract managing interactions with network's wrapped native token. /// @notice "wrapped native" refers to forks of WETH. -abstract contract WNativeBundler is BaseBundler { +abstract contract WNativeBundler is CoreBundler { using SafeTransferLib for ERC20; /* IMMUTABLES */ diff --git a/src/base/BaseBundlerV2.sol b/src/base/BaseBundlerV2.sol new file mode 100644 index 00000000..a24069d4 --- /dev/null +++ b/src/base/BaseBundlerV2.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity 0.8.24; + +import {CoreBundler} from "../CoreBundler.sol"; +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, + ERC4626Bundler, + WNativeBundler, + UrdBundler, + MorphoBundler, + ERC20WrapperBundler +{ + /* CONSTRUCTOR */ + + constructor(address morpho, address weth) WNativeBundler(weth) MorphoBundler(morpho) {} + + /* INTERNAL */ + + /// @inheritdoc MorphoBundler + function _isSenderAuthorized() internal view override(CoreBundler, MorphoBundler) returns (bool) { + return MorphoBundler._isSenderAuthorized(); + } +} diff --git a/src/ethereum/EthereumBundlerV2.sol b/src/ethereum/EthereumBundlerV2.sol index 94d9c262..9b71fd33 100644 --- a/src/ethereum/EthereumBundlerV2.sol +++ b/src/ethereum/EthereumBundlerV2.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import {MainnetLib} from "./libraries/MainnetLib.sol"; -import {BaseBundler} from "../BaseBundler.sol"; +import {CoreBundler} from "../CoreBundler.sol"; import {TransferBundler} from "../TransferBundler.sol"; import {EthereumPermitBundler} from "./EthereumPermitBundler.sol"; import {Permit2Bundler} from "../Permit2Bundler.sol"; @@ -36,7 +36,7 @@ contract EthereumBundlerV2 is /* INTERNAL */ /// @inheritdoc MorphoBundler - function _isSenderAuthorized() internal view override(BaseBundler, MorphoBundler) returns (bool) { + function _isSenderAuthorized() internal view override(CoreBundler, MorphoBundler) returns (bool) { return MorphoBundler._isSenderAuthorized(); } } diff --git a/src/goerli/GoerliBundlerV2.sol b/src/goerli/GoerliBundlerV2.sol index 973d0a0e..d1bb5527 100644 --- a/src/goerli/GoerliBundlerV2.sol +++ b/src/goerli/GoerliBundlerV2.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import {GoerliLib} from "./libraries/GoerliLib.sol"; -import {BaseBundler} from "../BaseBundler.sol"; +import {CoreBundler} from "../CoreBundler.sol"; import {TransferBundler} from "../TransferBundler.sol"; import {PermitBundler} from "../PermitBundler.sol"; import {Permit2Bundler} from "../Permit2Bundler.sol"; @@ -36,7 +36,7 @@ contract GoerliBundlerV2 is /* INTERNAL */ /// @inheritdoc MorphoBundler - function _isSenderAuthorized() internal view override(BaseBundler, MorphoBundler) returns (bool) { + function _isSenderAuthorized() internal view override(CoreBundler, MorphoBundler) returns (bool) { return MorphoBundler._isSenderAuthorized(); } } diff --git a/src/migration/AaveV2MigrationBundlerV2.sol b/src/migration/AaveV2MigrationBundlerV2.sol index 0ed2869e..e01b02f6 100644 --- a/src/migration/AaveV2MigrationBundlerV2.sol +++ b/src/migration/AaveV2MigrationBundlerV2.sol @@ -6,7 +6,7 @@ import {IAaveV2} from "./interfaces/IAaveV2.sol"; import {Math} from "../../lib/morpho-utils/src/math/Math.sol"; import {ErrorsLib} from "../libraries/ErrorsLib.sol"; -import {BaseBundler} from "../BaseBundler.sol"; +import {CoreBundler} from "../CoreBundler.sol"; import {StEthBundler} from "../StEthBundler.sol"; import {MigrationBundler, ERC20} from "./MigrationBundler.sol"; @@ -62,7 +62,7 @@ contract AaveV2MigrationBundlerV2 is MigrationBundler, StEthBundler { /* INTERNAL */ /// @inheritdoc MigrationBundler - function _isSenderAuthorized() internal view virtual override(BaseBundler, MigrationBundler) returns (bool) { + function _isSenderAuthorized() internal view virtual override(CoreBundler, MigrationBundler) returns (bool) { return MigrationBundler._isSenderAuthorized(); } } diff --git a/src/migration/CompoundV2MigrationBundlerV2.sol b/src/migration/CompoundV2MigrationBundlerV2.sol index b6d63923..15acaeaa 100644 --- a/src/migration/CompoundV2MigrationBundlerV2.sol +++ b/src/migration/CompoundV2MigrationBundlerV2.sol @@ -7,7 +7,7 @@ import {ICToken} from "./interfaces/ICToken.sol"; import {Math} from "../../lib/morpho-utils/src/math/Math.sol"; import {ErrorsLib} from "../libraries/ErrorsLib.sol"; -import {BaseBundler} from "../BaseBundler.sol"; +import {CoreBundler} from "../CoreBundler.sol"; import {WNativeBundler} from "../WNativeBundler.sol"; import {MigrationBundler, ERC20} from "./MigrationBundler.sol"; @@ -80,7 +80,7 @@ contract CompoundV2MigrationBundlerV2 is WNativeBundler, MigrationBundler { /* INTERNAL */ /// @inheritdoc MigrationBundler - function _isSenderAuthorized() internal view override(BaseBundler, MigrationBundler) returns (bool) { + function _isSenderAuthorized() internal view override(CoreBundler, MigrationBundler) returns (bool) { return MigrationBundler._isSenderAuthorized(); } } diff --git a/src/migration/MigrationBundler.sol b/src/migration/MigrationBundler.sol index 4955ef35..545054dc 100644 --- a/src/migration/MigrationBundler.sol +++ b/src/migration/MigrationBundler.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import {SafeTransferLib, ERC20} from "../../lib/solmate/src/utils/SafeTransferLib.sol"; -import {BaseBundler} from "../BaseBundler.sol"; +import {CoreBundler} from "../CoreBundler.sol"; import {TransferBundler} from "../TransferBundler.sol"; import {PermitBundler} from "../PermitBundler.sol"; import {Permit2Bundler} from "../Permit2Bundler.sol"; @@ -24,7 +24,7 @@ abstract contract MigrationBundler is TransferBundler, PermitBundler, Permit2Bun /* INTERNAL */ /// @inheritdoc MorphoBundler - function _isSenderAuthorized() internal view virtual override(BaseBundler, MorphoBundler) returns (bool) { + function _isSenderAuthorized() internal view virtual override(CoreBundler, MorphoBundler) returns (bool) { return MorphoBundler._isSenderAuthorized(); } } diff --git a/src/mocks/AgnosticBundler.sol b/src/mocks/AgnosticBundler.sol new file mode 100644 index 00000000..41ca66b0 --- /dev/null +++ b/src/mocks/AgnosticBundler.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity 0.8.24; + +import {CoreBundler} from "../CoreBundler.sol"; +import {TransferBundler} from "../TransferBundler.sol"; +import {PermitBundler} from "../PermitBundler.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"; + +/// @dev Mock contract, agnostic of the chain, used only for tests. +contract AgnosticBundler is + TransferBundler, + PermitBundler, + Permit2Bundler, + ERC4626Bundler, + WNativeBundler, + UrdBundler, + MorphoBundler, + ERC20WrapperBundler +{ + /* CONSTRUCTOR */ + + constructor(address morpho, address weth) WNativeBundler(weth) MorphoBundler(morpho) {} + + /* INTERNAL */ + + /// @inheritdoc MorphoBundler + function _isSenderAuthorized() internal view override(CoreBundler, MorphoBundler) returns (bool) { + return MorphoBundler._isSenderAuthorized(); + } +} diff --git a/src/mocks/bundlers/BaseBundlerMock.sol b/src/mocks/bundlers/BaseBundlerMock.sol deleted file mode 100644 index 4106d1f2..00000000 --- a/src/mocks/bundlers/BaseBundlerMock.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -import "../../BaseBundler.sol"; - -contract BaseBundlerMock is BaseBundler {} diff --git a/src/mocks/bundlers/ERC20WrapperBundlerMock.sol b/src/mocks/bundlers/ERC20WrapperBundlerMock.sol deleted file mode 100644 index d2b18e81..00000000 --- a/src/mocks/bundlers/ERC20WrapperBundlerMock.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -import "../../TransferBundler.sol"; -import {ERC20WrapperBundler} from "../../ERC20WrapperBundler.sol"; - -contract ERC20WrapperBundlerMock is ERC20WrapperBundler, TransferBundler {} diff --git a/src/mocks/bundlers/ERC4626BundlerMock.sol b/src/mocks/bundlers/ERC4626BundlerMock.sol deleted file mode 100644 index 3592d13b..00000000 --- a/src/mocks/bundlers/ERC4626BundlerMock.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -import "../../ERC4626Bundler.sol"; -import "../../TransferBundler.sol"; - -contract ERC4626BundlerMock is TransferBundler, ERC4626Bundler {} diff --git a/src/mocks/bundlers/MorphoBundlerMock.sol b/src/mocks/bundlers/MorphoBundlerMock.sol deleted file mode 100644 index 44db0852..00000000 --- a/src/mocks/bundlers/MorphoBundlerMock.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -import "../../TransferBundler.sol"; -import {MorphoBundler} from "../../MorphoBundler.sol"; - -contract MorphoBundlerMock is TransferBundler, MorphoBundler { - constructor(address morpho) MorphoBundler(morpho) {} - - function _isSenderAuthorized() internal view override(BaseBundler, MorphoBundler) returns (bool) { - return MorphoBundler._isSenderAuthorized(); - } -} diff --git a/src/mocks/bundlers/Permit2BundlerMock.sol b/src/mocks/bundlers/Permit2BundlerMock.sol deleted file mode 100644 index 4ac15b93..00000000 --- a/src/mocks/bundlers/Permit2BundlerMock.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -import "../../Permit2Bundler.sol"; - -contract Permit2BundlerMock is Permit2Bundler {} diff --git a/src/mocks/bundlers/PermitBundlerMock.sol b/src/mocks/bundlers/PermitBundlerMock.sol deleted file mode 100644 index a853670f..00000000 --- a/src/mocks/bundlers/PermitBundlerMock.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -import "../../TransferBundler.sol"; -import "../../PermitBundler.sol"; - -contract PermitBundlerMock is TransferBundler, PermitBundler {} diff --git a/src/mocks/bundlers/TransferBundlerMock.sol b/src/mocks/bundlers/TransferBundlerMock.sol deleted file mode 100644 index 0c189619..00000000 --- a/src/mocks/bundlers/TransferBundlerMock.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -import "../../TransferBundler.sol"; - -contract TransferBundlerMock is TransferBundler {} diff --git a/src/mocks/bundlers/UrdBundlerMock.sol b/src/mocks/bundlers/UrdBundlerMock.sol deleted file mode 100644 index 9f0de242..00000000 --- a/src/mocks/bundlers/UrdBundlerMock.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -import "../../UrdBundler.sol"; - -contract UrdBundlerMock is UrdBundler {} diff --git a/src/mocks/bundlers/WNativeBundlerMock.sol b/src/mocks/bundlers/WNativeBundlerMock.sol deleted file mode 100644 index 44841a57..00000000 --- a/src/mocks/bundlers/WNativeBundlerMock.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -import "../../WNativeBundler.sol"; -import "../../TransferBundler.sol"; - -contract WNativeBundlerMock is TransferBundler, WNativeBundler { - constructor(address wNative) WNativeBundler(wNative) {} -} diff --git a/src/mocks/bundlers/ethereum/EthereumPermitBundlerMock.sol b/src/mocks/bundlers/ethereum/EthereumPermitBundlerMock.sol deleted file mode 100644 index 4d72884e..00000000 --- a/src/mocks/bundlers/ethereum/EthereumPermitBundlerMock.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -import "../../../ethereum/EthereumPermitBundler.sol"; - -contract EthereumPermitBundlerMock is EthereumPermitBundler {} diff --git a/src/mocks/bundlers/ethereum/EthereumStEthBundlerMock.sol b/src/mocks/bundlers/ethereum/EthereumStEthBundlerMock.sol deleted file mode 100644 index 1329fd63..00000000 --- a/src/mocks/bundlers/ethereum/EthereumStEthBundlerMock.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -import "../../../TransferBundler.sol"; -import "../../../Permit2Bundler.sol"; -import "../../../ethereum/EthereumStEthBundler.sol"; - -contract EthereumStEthBundlerMock is TransferBundler, Permit2Bundler, EthereumStEthBundler {} diff --git a/src/sepolia/SepoliaBundlerV2.sol b/src/sepolia/SepoliaBundlerV2.sol index 4a33d9f2..df1237c2 100644 --- a/src/sepolia/SepoliaBundlerV2.sol +++ b/src/sepolia/SepoliaBundlerV2.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import {SepoliaLib} from "./libraries/SepoliaLib.sol"; -import {BaseBundler} from "../BaseBundler.sol"; +import {CoreBundler} from "../CoreBundler.sol"; import {TransferBundler} from "../TransferBundler.sol"; import {PermitBundler} from "../PermitBundler.sol"; import {Permit2Bundler} from "../Permit2Bundler.sol"; @@ -40,7 +40,7 @@ contract SepoliaBundlerV2 is /* INTERNAL */ /// @inheritdoc MorphoBundler - function _isSenderAuthorized() internal view override(BaseBundler, MorphoBundler) returns (bool) { + function _isSenderAuthorized() internal view override(CoreBundler, MorphoBundler) returns (bool) { return MorphoBundler._isSenderAuthorized(); } } diff --git a/test/forge/BaseBundlerEnshrinedLocalTest.sol b/test/forge/CoreBundlerEnshrinedLocalTest.sol similarity index 86% rename from test/forge/BaseBundlerEnshrinedLocalTest.sol rename to test/forge/CoreBundlerEnshrinedLocalTest.sol index 1eb048ee..c9396e64 100644 --- a/test/forge/BaseBundlerEnshrinedLocalTest.sol +++ b/test/forge/CoreBundlerEnshrinedLocalTest.sol @@ -1,11 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; -import {BaseBundler} from "src/mocks/bundlers/BaseBundlerMock.sol"; - import "./helpers/LocalTest.sol"; -contract BaseBundlerEnshrinedLocalTest is BaseBundler, LocalTest { +contract CoreBundlerEnshrinedLocalTest is CoreBundler, LocalTest { function checkInitiator(address expectedInitiator) public payable protected { require(initiator() == expectedInitiator, "unexpected initiator"); } diff --git a/test/forge/BaseBundlerLocalTest.sol b/test/forge/CoreBundlerLocalTest.sol similarity index 52% rename from test/forge/BaseBundlerLocalTest.sol rename to test/forge/CoreBundlerLocalTest.sol index 61c20b93..7a795c1e 100644 --- a/test/forge/BaseBundlerLocalTest.sol +++ b/test/forge/CoreBundlerLocalTest.sol @@ -1,25 +1,17 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; -import {ErrorsLib} from "src/libraries/ErrorsLib.sol"; - -import "src/mocks/bundlers/BaseBundlerMock.sol"; +import {ErrorsLib} from "../../src/libraries/ErrorsLib.sol"; import "./helpers/LocalTest.sol"; -contract BaseBundlerLocalTest is LocalTest { - function setUp() public override { - super.setUp(); - - bundler = new BaseBundlerMock(); - } - +contract CoreBundlerLocalTest is LocalTest { function testMulticallEmpty() public { bundler.multicall(bundle); } function testNestedMulticall() public { - bundle.push(abi.encodeCall(BaseBundler.multicall, (callbackBundle))); + bundle.push(abi.encodeCall(CoreBundler.multicall, (callbackBundle))); vm.expectRevert(bytes(ErrorsLib.ALREADY_INITIATED)); bundler.multicall(bundle); diff --git a/test/forge/ERC20WrapperBundlerLocalTest.sol b/test/forge/ERC20WrapperBundlerLocalTest.sol index 86725eb1..dd85be3a 100644 --- a/test/forge/ERC20WrapperBundlerLocalTest.sol +++ b/test/forge/ERC20WrapperBundlerLocalTest.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.0; import {ErrorsLib} from "../../src/libraries/ErrorsLib.sol"; -import {ERC20WrapperBundlerMock} from "../../src/mocks/bundlers/ERC20WrapperBundlerMock.sol"; import {ERC20WrapperMock, ERC20Wrapper} from "../../src/mocks/ERC20WrapperMock.sol"; import "./helpers/LocalTest.sol"; @@ -14,8 +13,6 @@ contract ERC20WrapperBundlerBundlerLocalTest is LocalTest { function setUp() public override { super.setUp(); - bundler = new ERC20WrapperBundlerMock(); - loanWrapper = new ERC20WrapperMock(loanToken, "Wrapped Loan Token", "WLT"); } diff --git a/test/forge/ERC4626BundlerLocalTest.sol b/test/forge/ERC4626BundlerLocalTest.sol index a7e985fc..c238db7b 100644 --- a/test/forge/ERC4626BundlerLocalTest.sol +++ b/test/forge/ERC4626BundlerLocalTest.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.0; import {ErrorsLib} from "../../src/libraries/ErrorsLib.sol"; import {ERC4626Mock} from "../../src/mocks/ERC4626Mock.sol"; -import "../../src/mocks/bundlers/ERC4626BundlerMock.sol"; import "./helpers/LocalTest.sol"; @@ -14,8 +13,6 @@ contract ERC4626BundlerLocalTest is LocalTest { function setUp() public override { super.setUp(); - bundler = new ERC4626BundlerMock(); - vault = new ERC4626Mock(address(loanToken), "LoanToken Vault", "BV"); vm.startPrank(USER); @@ -27,7 +24,7 @@ contract ERC4626BundlerLocalTest is LocalTest { function test4626MintUninitiated(uint256 shares) public { vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); - ERC4626BundlerMock(address(bundler)).erc4626Mint(address(vault), 0, shares, RECEIVER); + ERC4626Bundler(address(bundler)).erc4626Mint(address(vault), 0, shares, RECEIVER); } function testErc4626MintZeroAdressVault(uint256 shares) public { @@ -46,7 +43,7 @@ contract ERC4626BundlerLocalTest is LocalTest { function test4626DepositUninitiated(uint256 assets) public { vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); - ERC4626BundlerMock(address(bundler)).erc4626Deposit(address(vault), assets, 0, RECEIVER); + ERC4626Bundler(address(bundler)).erc4626Deposit(address(vault), assets, 0, RECEIVER); } function testErc4626DepositZeroAdressVault(uint256 assets) public { @@ -65,7 +62,7 @@ contract ERC4626BundlerLocalTest is LocalTest { function test4626WithdrawUninitiated(uint256 assets) public { vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); - ERC4626BundlerMock(address(bundler)).erc4626Withdraw(address(vault), assets, 0, RECEIVER, address(bundler)); + ERC4626Bundler(address(bundler)).erc4626Withdraw(address(vault), assets, 0, RECEIVER, address(bundler)); } function testErc4626WithdrawZeroAdressVault(uint256 assets) public { @@ -93,7 +90,7 @@ contract ERC4626BundlerLocalTest is LocalTest { function test4626RedeemUninitiated(uint256 shares) public { vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); - ERC4626BundlerMock(address(bundler)).erc4626Redeem(address(vault), shares, 0, RECEIVER, address(bundler)); + ERC4626Bundler(address(bundler)).erc4626Redeem(address(vault), shares, 0, RECEIVER, address(bundler)); } function testErc4626RedeemZeroAdressVault(uint256 shares) public { diff --git a/test/forge/MorphoBundlerLocalTest.sol b/test/forge/MorphoBundlerLocalTest.sol index c430b991..800334da 100644 --- a/test/forge/MorphoBundlerLocalTest.sol +++ b/test/forge/MorphoBundlerLocalTest.sol @@ -13,8 +13,6 @@ import {ErrorsLib} from "../../src/libraries/ErrorsLib.sol"; import {ErrorsLib as MorphoErrorsLib} from "../../lib/morpho-blue/src/libraries/ErrorsLib.sol"; import {MarketParamsLib} from "../../lib/morpho-blue/src/libraries/MarketParamsLib.sol"; -import "../../src/mocks/bundlers/MorphoBundlerMock.sol"; - import "./helpers/MetaMorphoLocalTest.sol"; contract MorphoBundlerLocalTest is MetaMorphoLocalTest { @@ -27,8 +25,6 @@ contract MorphoBundlerLocalTest is MetaMorphoLocalTest { function setUp() public override { super.setUp(); - bundler = new MorphoBundlerMock(address(morpho)); - vm.startPrank(USER); loanToken.approve(address(morpho), type(uint256).max); collateralToken.approve(address(morpho), type(uint256).max); @@ -226,7 +222,7 @@ contract MorphoBundlerLocalTest is MetaMorphoLocalTest { function testWithdrawUninitiated(uint256 withdrawnShares) public { vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); - MorphoBundlerMock(address(bundler)).morphoWithdraw(marketParams, 0, withdrawnShares, 0, RECEIVER); + MorphoBundler(address(bundler)).morphoWithdraw(marketParams, 0, withdrawnShares, 0, RECEIVER); } function testWithdraw(uint256 privateKey, uint256 amount, uint256 withdrawnShares) public { @@ -263,7 +259,7 @@ contract MorphoBundlerLocalTest is MetaMorphoLocalTest { function testBorrowUnititiated(uint256 borrowedAssets) public { vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); - MorphoBundlerMock(address(bundler)).morphoBorrow(marketParams, borrowedAssets, 0, type(uint256).max, RECEIVER); + MorphoBundler(address(bundler)).morphoBorrow(marketParams, borrowedAssets, 0, type(uint256).max, RECEIVER); } function _testSupplyCollateralBorrow(address user, uint256 amount, uint256 collateralAmount) internal { @@ -337,7 +333,7 @@ contract MorphoBundlerLocalTest is MetaMorphoLocalTest { function testWithdrawCollateralUninitiated(uint256 collateralAmount) public { vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); - MorphoBundlerMock(address(bundler)).morphoWithdrawCollateral(marketParams, collateralAmount, RECEIVER); + MorphoBundler(address(bundler)).morphoWithdrawCollateral(marketParams, collateralAmount, RECEIVER); } function _testRepayWithdrawCollateral(address user, uint256 collateralAmount) internal { diff --git a/test/forge/PermitBundlerLocalTest.sol b/test/forge/PermitBundlerLocalTest.sol index 20dfa92f..407a8fc2 100644 --- a/test/forge/PermitBundlerLocalTest.sol +++ b/test/forge/PermitBundlerLocalTest.sol @@ -3,7 +3,8 @@ pragma solidity ^0.8.0; import {SigUtils, Permit} from "./helpers/SigUtils.sol"; -import "../../src/mocks/bundlers/PermitBundlerMock.sol"; +import {ErrorsLib} from "../../src/libraries/ErrorsLib.sol"; +import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol"; import {ERC20PermitMock} from "../../src/mocks/ERC20PermitMock.sol"; import "./helpers/LocalTest.sol"; @@ -14,8 +15,6 @@ contract PermitBundlerLocalTest is LocalTest { function setUp() public override { super.setUp(); - bundler = new PermitBundlerMock(); - permitToken = new ERC20PermitMock("Permit Token", "PT"); } @@ -39,7 +38,7 @@ contract PermitBundlerLocalTest is LocalTest { amount = bound(amount, MIN_AMOUNT, MAX_AMOUNT); vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); - PermitBundlerMock(address(bundler)).permit(address(loanToken), amount, SIGNATURE_DEADLINE, 0, 0, 0, true); + PermitBundler(address(bundler)).permit(address(loanToken), amount, SIGNATURE_DEADLINE, 0, 0, 0, true); } function testPermitRevert(uint256 amount, uint256 privateKey, uint256 deadline) public { diff --git a/test/forge/TransferBundlerLocalTest.sol b/test/forge/TransferBundlerLocalTest.sol index 17030597..fd6f78ad 100644 --- a/test/forge/TransferBundlerLocalTest.sol +++ b/test/forge/TransferBundlerLocalTest.sol @@ -3,17 +3,9 @@ pragma solidity ^0.8.0; import {ErrorsLib} from "../../src/libraries/ErrorsLib.sol"; -import "../../src/mocks/bundlers/TransferBundlerMock.sol"; - import "./helpers/LocalTest.sol"; contract TransferBundlerLocalTest is LocalTest { - function setUp() public override { - super.setUp(); - - bundler = new TransferBundlerMock(); - } - function testTransfer(uint256 amount) public { amount = bound(amount, 0, MAX_AMOUNT); @@ -96,7 +88,7 @@ contract TransferBundlerLocalTest is LocalTest { amount = bound(amount, MIN_AMOUNT, MAX_AMOUNT); vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); - TransferBundlerMock(address(bundler)).erc20TransferFrom(address(loanToken), amount); + TransferBundler(address(bundler)).erc20TransferFrom(address(loanToken), amount); } function testTranferFromZeroAddress(uint256 amount) public { diff --git a/test/forge/UrdBundlerLocalTest.sol b/test/forge/UrdBundlerLocalTest.sol index 62dfa3ab..3d2b5ec5 100644 --- a/test/forge/UrdBundlerLocalTest.sol +++ b/test/forge/UrdBundlerLocalTest.sol @@ -9,8 +9,6 @@ import {ErrorsLib as UrdErrorsLib} from "../../lib/universal-rewards-distributor import {Merkle} from "../../lib/murky/src/Merkle.sol"; -import "../../src/mocks/bundlers/UrdBundlerMock.sol"; - import "./helpers/LocalTest.sol"; interface IUrdFactory { @@ -26,7 +24,6 @@ contract UrdBundlerLocalTest is LocalTest { function setUp() public override { super.setUp(); - bundler = new UrdBundlerMock(); urdFactory = IUrdFactory(deployCode("UrdFactory.sol", "")); vm.label(address(urdFactory), "UrdFactory"); merkle = new Merkle(); diff --git a/test/forge/ethereum/helpers/EthereumTest.sol b/test/forge/ethereum/helpers/EthereumTest.sol deleted file mode 100644 index ef7bf2f9..00000000 --- a/test/forge/ethereum/helpers/EthereumTest.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -import "../../../../config/ConfiguredEthereum.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(); - } - - function deal(address asset, address recipient, uint256 amount) internal virtual override { - if (asset == ST_ETH) { - if (amount == 0) return; - - deal(recipient, amount); - - vm.prank(recipient); - uint256 stEthAmount = IStEth(ST_ETH).submit{value: amount}(address(0)); - - vm.assume(stEthAmount != 0); - - return; - } - - return super.deal(asset, recipient, amount); - } -} diff --git a/test/forge/ethereum/EthereumBundlerEthereumTest.sol b/test/forge/fork/BundlerForkTest.sol similarity index 88% rename from test/forge/ethereum/EthereumBundlerEthereumTest.sol rename to test/forge/fork/BundlerForkTest.sol index 60e8c47b..8a5a6a4e 100644 --- a/test/forge/ethereum/EthereumBundlerEthereumTest.sol +++ b/test/forge/fork/BundlerForkTest.sol @@ -3,26 +3,18 @@ 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"; +import "./helpers/ForkTest.sol"; -contract EthereumBundlerEthereumTest is EthereumTest { +contract EthereumBundlerForkTest is ForkTest { using MathLib for uint256; using MorphoLib for IMorpho; using MorphoBalancesLib for IMorpho; using MarketParamsLib for MarketParams; using SafeTransferLib for ERC20; - function setUp() public override { - super.setUp(); - - bundler = new EthereumBundlerV2(address(morpho)); - - vm.prank(USER); - morpho.setAuthorization(address(bundler), true); - } - function testSupplyWithPermit2(uint256 seed, uint256 amount, address onBehalf, uint256 privateKey, uint256 deadline) public { diff --git a/test/forge/ethereum/Permit2BundlerEthereumTest.sol b/test/forge/fork/Permit2BundlerForkTest.sol similarity index 85% rename from test/forge/ethereum/Permit2BundlerEthereumTest.sol rename to test/forge/fork/Permit2BundlerForkTest.sol index 8bd35977..ee5e8c65 100644 --- a/test/forge/ethereum/Permit2BundlerEthereumTest.sol +++ b/test/forge/fork/Permit2BundlerForkTest.sol @@ -3,21 +3,13 @@ pragma solidity ^0.8.0; import {ErrorsLib} from "../../../src/libraries/ErrorsLib.sol"; -import "../../../src/mocks/bundlers/Permit2BundlerMock.sol"; - -import "./helpers/EthereumTest.sol"; +import "./helpers/ForkTest.sol"; error InvalidNonce(); -contract Permit2BundlerEthereumTest is EthereumTest { +contract Permit2BundlerForkTest is ForkTest { using SafeTransferLib for ERC20; - function setUp() public override { - super.setUp(); - - bundler = new Permit2BundlerMock(); - } - function testApprove2(uint256 seed, uint256 privateKey, uint256 deadline, uint256 amount) public { privateKey = bound(privateKey, 1, type(uint160).max); deadline = bound(deadline, block.timestamp, type(uint48).max); @@ -46,7 +38,7 @@ contract Permit2BundlerEthereumTest is EthereumTest { bytes memory signature; vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); - Permit2BundlerMock(address(bundler)).approve2(permitSingle, signature, false); + Permit2Bundler(address(bundler)).approve2(permitSingle, signature, false); } function testApprove2InvalidNonce(uint256 seed, uint256 privateKey, uint256 deadline, uint256 amount) public { @@ -74,6 +66,6 @@ contract Permit2BundlerEthereumTest is EthereumTest { function testTransferFrom2Uninitiated() public { vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); - Permit2BundlerMock(address(bundler)).transferFrom2(address(0), 0); + Permit2Bundler(address(bundler)).transferFrom2(address(0), 0); } } diff --git a/test/forge/ethereum/EthereumPermitBundlerEthereumTest.sol b/test/forge/fork/PermitBundlerForkTest.sol similarity index 81% rename from test/forge/ethereum/EthereumPermitBundlerEthereumTest.sol rename to test/forge/fork/PermitBundlerForkTest.sol index c4b2c474..6086a9be 100644 --- a/test/forge/ethereum/EthereumPermitBundlerEthereumTest.sol +++ b/test/forge/fork/PermitBundlerForkTest.sol @@ -5,21 +5,15 @@ import {ErrorsLib} from "../../../src/libraries/ErrorsLib.sol"; import {DaiPermit} from "../helpers/SigUtils.sol"; -import "../../../src/mocks/bundlers/ethereum/EthereumPermitBundlerMock.sol"; +import "../../../src/ethereum/EthereumPermitBundler.sol"; -import "./helpers/EthereumTest.sol"; +import "./helpers/ForkTest.sol"; /// @dev The unique EIP-712 domain domain separator for the DAI token contract on Ethereum. bytes32 constant DAI_DOMAIN_SEPARATOR = 0xdbb8cf42e1ecb028be3f3dbc922e1d878b963f411dc388ced501601c60f7c6f7; -contract EthereumPermitBundlerEthereumTest is EthereumTest { - function setUp() public override { - super.setUp(); - - bundler = new EthereumPermitBundlerMock(); - } - - function testPermitDai(uint256 privateKey, uint256 expiry) public { +contract PermitBundlerForkTest is ForkTest { + function testPermitDai(uint256 privateKey, uint256 expiry) public onlyEthereum { expiry = bound(expiry, block.timestamp, type(uint48).max); privateKey = bound(privateKey, 1, type(uint160).max); @@ -34,12 +28,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); + EthereumPermitBundler(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); diff --git a/test/forge/ethereum/EthereumStEthBundlerEthereumTest.sol b/test/forge/fork/StEthBundlerForkTest.sol similarity index 89% rename from test/forge/ethereum/EthereumStEthBundlerEthereumTest.sol rename to test/forge/fork/StEthBundlerForkTest.sol index a933424a..44415bfe 100644 --- a/test/forge/ethereum/EthereumStEthBundlerEthereumTest.sol +++ b/test/forge/fork/StEthBundlerForkTest.sol @@ -5,22 +5,26 @@ import {IAllowanceTransfer} from "../../../lib/permit2/src/interfaces/IAllowance import {ErrorsLib} from "../../../src/libraries/ErrorsLib.sol"; -import "../../../src/mocks/bundlers/ethereum/EthereumStEthBundlerMock.sol"; +import "../../../src/ethereum/EthereumStEthBundler.sol"; -import "./helpers/EthereumTest.sol"; +import "./helpers/ForkTest.sol"; bytes32 constant BEACON_BALANCE_POSITION = 0xa66d35f054e68143c18f32c990ed5cb972bb68a68f500cd2dd3a16bbf3686483; // keccak256("lido.Lido.beaconBalance"); -contract EthereumStEthBundlerEthereumTest is EthereumTest { +contract EthereumStEthBundlerMock is TransferBundler, Permit2Bundler, EthereumStEthBundler {} + +contract EthereumStEthBundlerForkTest is ForkTest { 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)); @@ -28,7 +32,7 @@ contract EthereumStEthBundlerEthereumTest is EthereumTest { bundler.multicall(bundle); } - function testStakeEth(uint256 amount) public { + function testStakeEth(uint256 amount) public onlyEthereum { amount = bound(amount, MIN_AMOUNT, 10_000 ether); uint256 shares = IStEth(ST_ETH).getSharesByPooledEth(amount); @@ -49,7 +53,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); @@ -66,7 +70,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); @@ -82,7 +86,7 @@ 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)); @@ -90,7 +94,7 @@ contract EthereumStEthBundlerEthereumTest is EthereumTest { 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); @@ -121,7 +125,7 @@ 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)); @@ -129,7 +133,7 @@ contract EthereumStEthBundlerEthereumTest is EthereumTest { 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); diff --git a/test/forge/ethereum/WNativeBundlerEthereumTest.sol b/test/forge/fork/WNativeBundlerForkTest.sol similarity index 92% rename from test/forge/ethereum/WNativeBundlerEthereumTest.sol rename to test/forge/fork/WNativeBundlerForkTest.sol index 2b3bc7c0..8d290465 100644 --- a/test/forge/ethereum/WNativeBundlerEthereumTest.sol +++ b/test/forge/fork/WNativeBundlerForkTest.sol @@ -3,16 +3,12 @@ pragma solidity ^0.8.0; import {ErrorsLib} from "../../../src/libraries/ErrorsLib.sol"; -import "../../../src/mocks/bundlers/WNativeBundlerMock.sol"; +import "./helpers/ForkTest.sol"; -import "./helpers/EthereumTest.sol"; - -contract WNativeBundlerEthereumTest is EthereumTest { +contract WNativeBundlerForkTest is ForkTest { function setUp() public override { super.setUp(); - bundler = new WNativeBundlerMock(WETH); - vm.prank(USER); ERC20(WETH).approve(address(bundler), type(uint256).max); } diff --git a/test/forge/helpers/ForkTest.sol b/test/forge/fork/helpers/ForkTest.sol similarity index 70% rename from test/forge/helpers/ForkTest.sol rename to test/forge/fork/helpers/ForkTest.sol index c10b7924..40fc76d1 100644 --- a/test/forge/helpers/ForkTest.sol +++ b/test/forge/fork/helpers/ForkTest.sol @@ -1,24 +1,25 @@ // SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.0; -import {IStEth} from "../../../src/interfaces/IStEth.sol"; -import {IWstEth} from "../../../src/interfaces/IWstEth.sol"; -import {IAllowanceTransfer} from "../../../lib/permit2/src/interfaces/IAllowanceTransfer.sol"; +import {IStEth} from "../../../../src/interfaces/IStEth.sol"; +import {IWstEth} from "../../../../src/interfaces/IWstEth.sol"; +import {IAllowanceTransfer} from "../../../../lib/permit2/src/interfaces/IAllowanceTransfer.sol"; -import {Permit2Lib} from "../../../lib/permit2/src/libraries/Permit2Lib.sol"; +import {Permit2Lib} from "../../../../lib/permit2/src/libraries/Permit2Lib.sol"; -import {Permit2Bundler} from "../../../src/Permit2Bundler.sol"; -import {WNativeBundler} from "../../../src/WNativeBundler.sol"; -import {StEthBundler} from "../../../src/StEthBundler.sol"; +import {Permit2Bundler} from "../../../../src/Permit2Bundler.sol"; +import {WNativeBundler} from "../../../../src/WNativeBundler.sol"; +import {StEthBundler} from "../../../../src/StEthBundler.sol"; +import {EthereumBundlerV2} from "../../../../src/ethereum/EthereumBundlerV2.sol"; +import {BaseBundlerV2} from "../../../../src/base/BaseBundlerV2.sol"; -import "../../../config/Configured.sol"; -import "./BaseTest.sol"; +import "../../../../config/Configured.sol"; +import "../../helpers/CommonTest.sol"; -abstract contract ForkTest is BaseTest, Configured { +abstract contract ForkTest is CommonTest, Configured { using ConfigLib for Config; using SafeTransferLib for ERC20; - string internal network; uint256 internal forkId; uint256 internal snapshotId = type(uint256).max; @@ -26,7 +27,9 @@ abstract contract ForkTest is BaseTest, Configured { MarketParams[] allMarketParams; function setUp() public virtual override { - _initConfig(); + // Run fork tests on Ethereum by default. + if (block.chainid == 31337) vm.chainId(1); + _loadConfig(); _fork(); @@ -34,6 +37,12 @@ abstract contract ForkTest is BaseTest, Configured { super.setUp(); + if (block.chainid == 1) { + bundler = new EthereumBundlerV2(address(morpho)); + } else if (block.chainid == 8453) { + bundler = new BaseBundlerV2(address(morpho), address(WETH)); + } + for (uint256 i; i < configMarkets.length; ++i) { ConfigMarket memory configMarket = configMarkets[i]; @@ -52,10 +61,13 @@ abstract contract ForkTest is BaseTest, Configured { allMarketParams.push(marketParams); } + + vm.prank(USER); + morpho.setAuthorization(address(bundler), true); } function _fork() internal virtual { - string memory rpcUrl = vm.rpcUrl(_network()); + string memory rpcUrl = vm.rpcUrl(network); uint256 forkBlockNumber = CONFIG.getForkBlockNumber(); forkId = forkBlockNumber == 0 ? vm.createSelectFork(rpcUrl) : vm.createSelectFork(rpcUrl, forkBlockNumber); @@ -66,9 +78,11 @@ abstract contract ForkTest is BaseTest, Configured { function _label() internal virtual { for (uint256 i; i < allAssets.length; ++i) { address asset = allAssets[i]; - string memory symbol = ERC20(asset).symbol(); + if (asset != address(0)) { + string memory symbol = ERC20(asset).symbol(); - vm.label(asset, symbol); + vm.label(asset, symbol); + } } } @@ -77,9 +91,27 @@ abstract contract ForkTest is BaseTest, Configured { if (asset == WETH) super.deal(WETH, WETH.balance + amount); // Refill wrapped Ether. + if (asset == ST_ETH) { + if (amount == 0) return; + + deal(recipient, amount); + + vm.prank(recipient); + uint256 stEthAmount = IStEth(ST_ETH).submit{value: amount}(address(0)); + + vm.assume(stEthAmount != 0); + + return; + } + return super.deal(asset, recipient, amount); } + modifier onlyEthereum() { + vm.skip(block.chainid != 1); + _; + } + /// @dev Reverts the fork to its initial fork state. function _revert() internal { if (snapshotId < type(uint256).max) vm.revertTo(snapshotId); diff --git a/test/forge/ethereum/migration/AaveV2MigrationBundlerEthereumTest.sol b/test/forge/fork/migration/AaveV2MigrationBundlerForkTest.sol similarity index 95% rename from test/forge/ethereum/migration/AaveV2MigrationBundlerEthereumTest.sol rename to test/forge/fork/migration/AaveV2MigrationBundlerForkTest.sol index 0815b54a..a2467beb 100644 --- a/test/forge/ethereum/migration/AaveV2MigrationBundlerEthereumTest.sol +++ b/test/forge/fork/migration/AaveV2MigrationBundlerForkTest.sol @@ -7,9 +7,9 @@ import {IERC4626} from "../../../../lib/openzeppelin-contracts/contracts/interfa import "../../../../src/migration/AaveV2MigrationBundlerV2.sol"; -import "./helpers/EthereumMigrationTest.sol"; +import "./helpers/MigrationForkTest.sol"; -contract AaveV2MigrationBundlerEthereumTest is EthereumMigrationTest { +contract AaveV2MigrationBundlerForkTest is MigrationForkTest { using SafeTransferLib for ERC20; using MarketParamsLib for MarketParams; using MorphoLib for IMorpho; @@ -21,6 +21,8 @@ contract AaveV2MigrationBundlerEthereumTest is EthereumMigrationTest { uint256 borrowed = 1 ether; function setUp() public override { + if (block.chainid != 1) return; + super.setUp(); _initMarket(DAI, WETH); @@ -30,28 +32,28 @@ contract AaveV2MigrationBundlerEthereumTest is EthereumMigrationTest { bundler = new AaveV2MigrationBundlerV2(address(morpho), AAVE_V2_POOL, WST_ETH); } - function testAaveV2RepayUninitiated(uint256 amount) public { + function testAaveV2RepayUninitiated(uint256 amount) public onlyEthereum { amount = bound(amount, MIN_AMOUNT, MAX_AMOUNT); vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); AaveV2MigrationBundlerV2(address(bundler)).aaveV2Repay(marketParams.loanToken, amount, 1); } - function testAaveV2WithdrawUninitiated(uint256 amount) public { + function testAaveV2WithdrawUninitiated(uint256 amount) public onlyEthereum { amount = bound(amount, MIN_AMOUNT, MAX_AMOUNT); vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); AaveV2MigrationBundlerV2(address(bundler)).aaveV2Withdraw(marketParams.loanToken, amount); } - function testAaveV2RepayZeroAmount() public { + function testAaveV2RepayZeroAmount() public onlyEthereum { bundle.push(_aaveV2Repay(marketParams.loanToken, 0)); vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); bundler.multicall(bundle); } - function testMigrateBorrowerWithPermit2(uint256 privateKey) public { + function testMigrateBorrowerWithPermit2(uint256 privateKey) public onlyEthereum { address user; (privateKey, user) = _boundPrivateKey(privateKey); @@ -88,7 +90,7 @@ contract AaveV2MigrationBundlerEthereumTest is EthereumMigrationTest { _assertBorrowerPosition(collateralSupplied, borrowed, user, address(bundler)); } - function testMigrateBorrowerDaiToSDaiWithPermit2(uint256 privateKey) public { + function testMigrateBorrowerDaiToSDaiWithPermit2(uint256 privateKey) public onlyEthereum { address user; (privateKey, user) = _boundPrivateKey(privateKey); @@ -129,7 +131,7 @@ contract AaveV2MigrationBundlerEthereumTest is EthereumMigrationTest { _assertBorrowerPosition(sDaiAmount, borrowed, user, address(bundler)); } - function testMigrateStEthPositionWithPermit2(uint256 privateKey) public { + function testMigrateStEthPositionWithPermit2(uint256 privateKey) public onlyEthereum { address user; (privateKey, user) = _boundPrivateKey(privateKey); @@ -175,7 +177,7 @@ contract AaveV2MigrationBundlerEthereumTest is EthereumMigrationTest { _assertBorrowerPosition(wstEthAmount, borrowed, user, address(bundler)); } - function testMigrateSupplierWithPermit2(uint256 privateKey, uint256 supplied) public { + function testMigrateSupplierWithPermit2(uint256 privateKey, uint256 supplied) public onlyEthereum { address user; (privateKey, user) = _boundPrivateKey(privateKey); supplied = bound(supplied, 100, 100 ether); @@ -204,7 +206,7 @@ contract AaveV2MigrationBundlerEthereumTest is EthereumMigrationTest { _assertSupplierPosition(supplied, user, address(bundler)); } - function testMigrateSupplierToVaultWithPermit2(uint256 privateKey, uint256 supplied) public { + function testMigrateSupplierToVaultWithPermit2(uint256 privateKey, uint256 supplied) public onlyEthereum { address user; (privateKey, user) = _boundPrivateKey(privateKey); supplied = bound(supplied, 100, 100 ether); diff --git a/test/forge/ethereum/migration/AaveV3MigrationBundlerEthereumTest.sol b/test/forge/fork/migration/AaveV3MigrationBundlerForkTest.sol similarity index 96% rename from test/forge/ethereum/migration/AaveV3MigrationBundlerEthereumTest.sol rename to test/forge/fork/migration/AaveV3MigrationBundlerForkTest.sol index 76a9ffb3..a54829d0 100644 --- a/test/forge/ethereum/migration/AaveV3MigrationBundlerEthereumTest.sol +++ b/test/forge/fork/migration/AaveV3MigrationBundlerForkTest.sol @@ -7,9 +7,9 @@ import {IAaveV3} from "../../../../src/migration/interfaces/IAaveV3.sol"; import {SigUtils, Permit} from "../../helpers/SigUtils.sol"; import "../../../../src/migration/AaveV3MigrationBundlerV2.sol"; -import "./helpers/EthereumMigrationTest.sol"; +import "./helpers/MigrationForkTest.sol"; -contract AaveV3MigrationBundlerEthereumTest is EthereumMigrationTest { +contract AaveV3MigrationBundlerForkTest is MigrationForkTest { using SafeTransferLib for ERC20; using MarketParamsLib for MarketParams; using MorphoLib for IMorpho; @@ -17,13 +17,21 @@ contract AaveV3MigrationBundlerEthereumTest is EthereumMigrationTest { uint256 public constant RATE_MODE = 2; - uint256 collateralSupplied = 10_000 ether; + uint256 collateralSupplied; uint256 borrowed = 1 ether; function setUp() public override { super.setUp(); - _initMarket(DAI, WETH); + if (block.chainid == 1) { + _initMarket(DAI, WETH); + collateralSupplied = 10_000 ether; + } + if (block.chainid == 8453) { + _initMarket(CB_ETH, WETH); + // To avoid getting above the Aave supply cap. + collateralSupplied = 2 ether; + } vm.label(AAVE_V3_POOL, "Aave V3 Pool"); @@ -116,7 +124,7 @@ contract AaveV3MigrationBundlerEthereumTest is EthereumMigrationTest { _assertBorrowerPosition(collateralSupplied, borrowed, user, address(bundler)); } - function testMigrateUSDTPositionWithPermit2(uint256 privateKey) public { + function testMigrateUSDTPositionWithPermit2(uint256 privateKey) public onlyEthereum { address user; (privateKey, user) = _boundPrivateKey(privateKey); diff --git a/test/forge/ethereum/migration/AaveV3OptimizerMigrationBundlerEthereumTest.sol b/test/forge/fork/migration/AaveV3OptimizerMigrationBundlerForkTest.sol similarity index 94% rename from test/forge/ethereum/migration/AaveV3OptimizerMigrationBundlerEthereumTest.sol rename to test/forge/fork/migration/AaveV3OptimizerMigrationBundlerForkTest.sol index 3102487e..ebec2285 100644 --- a/test/forge/ethereum/migration/AaveV3OptimizerMigrationBundlerEthereumTest.sol +++ b/test/forge/fork/migration/AaveV3OptimizerMigrationBundlerForkTest.sol @@ -5,9 +5,9 @@ import {Authorization as AaveV3OptimizerAuthorization} from "../../../../src/mig import "../../../../src/migration/AaveV3OptimizerMigrationBundlerV2.sol"; -import "./helpers/EthereumMigrationTest.sol"; +import "./helpers/MigrationForkTest.sol"; -contract AaveV3OptimizerMigrationBundlerEthereumTest is EthereumMigrationTest { +contract AaveV3OptimizerMigrationBundlerForkTest is MigrationForkTest { using SafeTransferLib for ERC20; using MarketParamsLib for MarketParams; using MorphoLib for IMorpho; @@ -19,6 +19,8 @@ contract AaveV3OptimizerMigrationBundlerEthereumTest is EthereumMigrationTest { uint256 borrowed = 1 ether; function setUp() public override { + if (block.chainid != 1) return; + super.setUp(); _initMarket(DAI, WETH); @@ -28,21 +30,21 @@ contract AaveV3OptimizerMigrationBundlerEthereumTest is EthereumMigrationTest { bundler = new AaveV3OptimizerMigrationBundlerV2(address(morpho), address(AAVE_V3_OPTIMIZER)); } - function testAaveV3OptimizerRepayUninitiated(uint256 amount) public { + function testAaveV3OptimizerRepayUninitiated(uint256 amount) public onlyEthereum { amount = bound(amount, MIN_AMOUNT, MAX_AMOUNT); vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); AaveV3OptimizerMigrationBundlerV2(address(bundler)).aaveV3OptimizerRepay(marketParams.loanToken, amount); } - function testAaveV3Optimizer3RepayZeroAmount() public { + function testAaveV3Optimizer3RepayZeroAmount() public onlyEthereum { bundle.push(_aaveV3OptimizerRepay(marketParams.loanToken, 0)); vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); bundler.multicall(bundle); } - function testAaveV3OtimizerAuthorizationWithSigRevert(uint256 privateKey, address owner) public { + function testAaveV3OtimizerAuthorizationWithSigRevert(uint256 privateKey, address owner) public onlyEthereum { address user; (privateKey, user) = _boundPrivateKey(privateKey); @@ -68,7 +70,7 @@ contract AaveV3OptimizerMigrationBundlerEthereumTest is EthereumMigrationTest { bundler.multicall(bundle); } - function testMigrateBorrowerWithOptimizerPermit(uint256 privateKey) public { + function testMigrateBorrowerWithOptimizerPermit(uint256 privateKey) public onlyEthereum { address user; (privateKey, user) = _boundPrivateKey(privateKey); @@ -99,7 +101,7 @@ contract AaveV3OptimizerMigrationBundlerEthereumTest is EthereumMigrationTest { _assertBorrowerPosition(collateralSupplied, borrowed, user, address(bundler)); } - function testMigrateUSDTBorrowerWithOptimizerPermit(uint256 privateKey) public { + function testMigrateUSDTBorrowerWithOptimizerPermit(uint256 privateKey) public onlyEthereum { address user; (privateKey, user) = _boundPrivateKey(privateKey); @@ -135,7 +137,7 @@ contract AaveV3OptimizerMigrationBundlerEthereumTest is EthereumMigrationTest { _assertBorrowerPosition(amountUsdt, borrowed, user, address(bundler)); } - function testMigrateSupplierWithOptimizerPermit(uint256 privateKey, uint256 supplied) public { + function testMigrateSupplierWithOptimizerPermit(uint256 privateKey, uint256 supplied) public onlyEthereum { address user; (privateKey, user) = _boundPrivateKey(privateKey); supplied = bound(supplied, 100, 100 ether); @@ -158,7 +160,7 @@ contract AaveV3OptimizerMigrationBundlerEthereumTest is EthereumMigrationTest { _assertSupplierPosition(supplied, user, address(bundler)); } - function testMigrateSupplierToVaultWithOptimizerPermit(uint256 privateKey, uint256 supplied) public { + function testMigrateSupplierToVaultWithOptimizerPermit(uint256 privateKey, uint256 supplied) public onlyEthereum { address user; (privateKey, user) = _boundPrivateKey(privateKey); supplied = bound(supplied, 100, 100 ether); @@ -181,7 +183,7 @@ contract AaveV3OptimizerMigrationBundlerEthereumTest is EthereumMigrationTest { _assertVaultSupplierPosition(supplied, user, address(bundler)); } - function testAaveV3OptimizerApproveManagerUninitiated(uint256 amount) public { + function testAaveV3OptimizerApproveManagerUninitiated(uint256 amount) public onlyEthereum { amount = bound(amount, MIN_AMOUNT, MAX_AMOUNT); Signature memory sig; @@ -192,7 +194,7 @@ contract AaveV3OptimizerMigrationBundlerEthereumTest is EthereumMigrationTest { ); } - function testAaveV3OptimizerWithdrawUninitiated(uint256 amount) public { + function testAaveV3OptimizerWithdrawUninitiated(uint256 amount) public onlyEthereum { amount = bound(amount, MIN_AMOUNT, MAX_AMOUNT); vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); @@ -201,7 +203,7 @@ contract AaveV3OptimizerMigrationBundlerEthereumTest is EthereumMigrationTest { ); } - function testAaveV3OptimizerWithdrawCollateralUninitiated(uint256 amount) public { + function testAaveV3OptimizerWithdrawCollateralUninitiated(uint256 amount) public onlyEthereum { amount = bound(amount, MIN_AMOUNT, MAX_AMOUNT); vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); diff --git a/test/forge/ethereum/migration/CompoundV2EthBorrowableMigrationBundlerEthereumTest.sol b/test/forge/fork/migration/CompoundV2EthBorrowableMigrationBundlerForkTest.sol similarity index 93% rename from test/forge/ethereum/migration/CompoundV2EthBorrowableMigrationBundlerEthereumTest.sol rename to test/forge/fork/migration/CompoundV2EthBorrowableMigrationBundlerForkTest.sol index 39d0d909..956d777e 100644 --- a/test/forge/ethereum/migration/CompoundV2EthBorrowableMigrationBundlerEthereumTest.sol +++ b/test/forge/fork/migration/CompoundV2EthBorrowableMigrationBundlerForkTest.sol @@ -5,9 +5,9 @@ import {IComptroller} from "../../../../src/migration/interfaces/IComptroller.so import "../../../../src/migration/CompoundV2MigrationBundlerV2.sol"; -import "./helpers/EthereumMigrationTest.sol"; +import "./helpers/MigrationForkTest.sol"; -contract CompoundV2EthLoanMigrationBundlerEthereumTest is EthereumMigrationTest { +contract CompoundV2EthLoanMigrationBundlerForkTest is MigrationForkTest { using MathLib for uint256; using SafeTransferLib for ERC20; using MarketParamsLib for MarketParams; @@ -17,6 +17,8 @@ contract CompoundV2EthLoanMigrationBundlerEthereumTest is EthereumMigrationTest address[] internal enteredMarkets; function setUp() public override { + if (block.chainid != 1) return; + super.setUp(); _initMarket(DAI, WETH); @@ -26,21 +28,21 @@ contract CompoundV2EthLoanMigrationBundlerEthereumTest is EthereumMigrationTest enteredMarkets.push(C_DAI_V2); } - function testCompoundV2RepayUninitiated(uint256 amount) public { + function testCompoundV2RepayUninitiated(uint256 amount) public onlyEthereum { amount = bound(amount, MIN_AMOUNT, MAX_AMOUNT); vm.expectRevert(bytes(ErrorsLib.UNINITIATED)); CompoundV2MigrationBundlerV2(payable(address(bundler))).compoundV2Repay(C_DAI_V2, amount); } - function testCompoundV2RepayCEthZeroAmount() public { + function testCompoundV2RepayCEthZeroAmount() public onlyEthereum { bundle.push(_compoundV2Repay(C_ETH_V2, 0)); vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); bundler.multicall(bundle); } - function testMigrateBorrowerWithPermit2(uint256 privateKey) public { + function testMigrateBorrowerWithPermit2(uint256 privateKey) public onlyEthereum { uint256 collateral = 10_000 ether; uint256 borrowed = 1 ether; @@ -82,7 +84,7 @@ contract CompoundV2EthLoanMigrationBundlerEthereumTest is EthereumMigrationTest _assertBorrowerPosition(collateral, borrowed, user, address(bundler)); } - function testMigrateSupplierWithPermit2(uint256 privateKey, uint256 supplied) public { + function testMigrateSupplierWithPermit2(uint256 privateKey, uint256 supplied) public onlyEthereum { address user; (privateKey, user) = _boundPrivateKey(privateKey); supplied = bound(supplied, 0.1 ether, 100 ether); @@ -110,7 +112,7 @@ contract CompoundV2EthLoanMigrationBundlerEthereumTest is EthereumMigrationTest _assertSupplierPosition(supplied, user, address(bundler)); } - function testMigrateSupplierToVaultWithPermit2(uint256 privateKey, uint256 supplied) public { + function testMigrateSupplierToVaultWithPermit2(uint256 privateKey, uint256 supplied) public onlyEthereum { address user; (privateKey, user) = _boundPrivateKey(privateKey); supplied = bound(supplied, 0.1 ether, 100 ether); diff --git a/test/forge/ethereum/migration/CompoundV2EthCollateralMigrationBundlerEthereumTest.sol b/test/forge/fork/migration/CompoundV2EthCollateralMigrationBundlerForkTest.sol similarity index 92% rename from test/forge/ethereum/migration/CompoundV2EthCollateralMigrationBundlerEthereumTest.sol rename to test/forge/fork/migration/CompoundV2EthCollateralMigrationBundlerForkTest.sol index e09d1e58..e4c08e98 100644 --- a/test/forge/ethereum/migration/CompoundV2EthCollateralMigrationBundlerEthereumTest.sol +++ b/test/forge/fork/migration/CompoundV2EthCollateralMigrationBundlerForkTest.sol @@ -5,9 +5,9 @@ import {IComptroller} from "../../../../src/migration/interfaces/IComptroller.so import "../../../../src/migration/CompoundV2MigrationBundlerV2.sol"; -import "./helpers/EthereumMigrationTest.sol"; +import "./helpers/MigrationForkTest.sol"; -contract CompoundV2EthCollateralMigrationBundlerEthereumTest is EthereumMigrationTest { +contract CompoundV2EthCollateralMigrationBundlerForkTest is MigrationForkTest { using MathLib for uint256; using SafeTransferLib for ERC20; using MarketParamsLib for MarketParams; @@ -17,6 +17,8 @@ contract CompoundV2EthCollateralMigrationBundlerEthereumTest is EthereumMigratio address[] internal enteredMarkets; function setUp() public override { + if (block.chainid != 1) return; + super.setUp(); _initMarket(WETH, DAI); @@ -26,14 +28,14 @@ contract CompoundV2EthCollateralMigrationBundlerEthereumTest is EthereumMigratio enteredMarkets.push(C_ETH_V2); } - function testCompoundV2RepayZeroAmount() public { + function testCompoundV2RepayZeroAmount() public onlyEthereum { bundle.push(_compoundV2Repay(C_DAI_V2, 0)); vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); bundler.multicall(bundle); } - function testMigrateBorrowerWithPermit2(uint256 privateKey) public { + function testMigrateBorrowerWithPermit2(uint256 privateKey) public onlyEthereum { uint256 collateral = 10 ether; uint256 borrowed = 1 ether; diff --git a/test/forge/ethereum/migration/CompoundV2NoEthMigrationBundlerEthereumTest.sol b/test/forge/fork/migration/CompoundV2NoEthMigrationBundlerForkTest.sol similarity index 94% rename from test/forge/ethereum/migration/CompoundV2NoEthMigrationBundlerEthereumTest.sol rename to test/forge/fork/migration/CompoundV2NoEthMigrationBundlerForkTest.sol index ad19be65..6c2aada0 100644 --- a/test/forge/ethereum/migration/CompoundV2NoEthMigrationBundlerEthereumTest.sol +++ b/test/forge/fork/migration/CompoundV2NoEthMigrationBundlerForkTest.sol @@ -5,9 +5,9 @@ import {IComptroller} from "../../../../src/migration/interfaces/IComptroller.so import "../../../../src/migration/CompoundV2MigrationBundlerV2.sol"; -import "./helpers/EthereumMigrationTest.sol"; +import "./helpers/MigrationForkTest.sol"; -contract CompoundV2NoEthMigrationBundlerEthereumTest is EthereumMigrationTest { +contract CompoundV2NoEthMigrationBundlerForkTest is MigrationForkTest { using MathLib for uint256; using SafeTransferLib for ERC20; using MarketParamsLib for MarketParams; @@ -17,6 +17,8 @@ contract CompoundV2NoEthMigrationBundlerEthereumTest is EthereumMigrationTest { address[] internal enteredMarkets; function setUp() public override { + if (block.chainid != 1) return; + super.setUp(); _initMarket(DAI, USDC); @@ -26,14 +28,14 @@ contract CompoundV2NoEthMigrationBundlerEthereumTest is EthereumMigrationTest { enteredMarkets.push(C_DAI_V2); } - function testCompoundV2RedeemZeroAmount() public { + function testCompoundV2RedeemZeroAmount() public onlyEthereum { bundle.push(_compoundV2Redeem(C_USDC_V2, 0)); vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); bundler.multicall(bundle); } - function testMigrateBorrowerWithPermit2(uint256 privateKey) public { + function testMigrateBorrowerWithPermit2(uint256 privateKey) public onlyEthereum { uint256 collateral = 10 ether; uint256 borrowed = 1e6; @@ -73,7 +75,7 @@ contract CompoundV2NoEthMigrationBundlerEthereumTest is EthereumMigrationTest { _assertBorrowerPosition(collateral, borrowed, user, address(bundler)); } - function testMigrateSupplierWithPermit2(uint256 privateKey, uint256 supplied) public { + function testMigrateSupplierWithPermit2(uint256 privateKey, uint256 supplied) public onlyEthereum { address user; (privateKey, user) = _boundPrivateKey(privateKey); supplied = bound(supplied, 100, 100 ether); @@ -102,7 +104,7 @@ contract CompoundV2NoEthMigrationBundlerEthereumTest is EthereumMigrationTest { _assertSupplierPosition(supplied, user, address(bundler)); } - function testMigrateSupplierToVaultWithPermit2(uint256 privateKey, uint256 supplied) public { + function testMigrateSupplierToVaultWithPermit2(uint256 privateKey, uint256 supplied) public onlyEthereum { address user; (privateKey, user) = _boundPrivateKey(privateKey); supplied = bound(supplied, 100, 100 ether); diff --git a/test/forge/ethereum/migration/CompoundV3MigrationBundlerEthereumTest.sol b/test/forge/fork/migration/CompoundV3MigrationBundlerForkTest.sol similarity index 98% rename from test/forge/ethereum/migration/CompoundV3MigrationBundlerEthereumTest.sol rename to test/forge/fork/migration/CompoundV3MigrationBundlerForkTest.sol index b0a49eb9..4671cc2e 100644 --- a/test/forge/ethereum/migration/CompoundV3MigrationBundlerEthereumTest.sol +++ b/test/forge/fork/migration/CompoundV3MigrationBundlerForkTest.sol @@ -5,9 +5,9 @@ import {CompoundV3Authorization} from "../../helpers/SigUtils.sol"; import "../../../../src/migration/CompoundV3MigrationBundlerV2.sol"; -import "./helpers/EthereumMigrationTest.sol"; +import "./helpers/MigrationForkTest.sol"; -contract CompoundV3MigrationBundlerEthereumTest is EthereumMigrationTest { +contract CompoundV3MigrationBundlerForkTest is MigrationForkTest { using SafeTransferLib for ERC20; using MarketParamsLib for MarketParams; using MorphoLib for IMorpho; diff --git a/test/forge/ethereum/migration/helpers/EthereumMigrationTest.sol b/test/forge/fork/migration/helpers/MigrationForkTest.sol similarity index 95% rename from test/forge/ethereum/migration/helpers/EthereumMigrationTest.sol rename to test/forge/fork/migration/helpers/MigrationForkTest.sol index cda3e674..ae241ec7 100644 --- a/test/forge/ethereum/migration/helpers/EthereumMigrationTest.sol +++ b/test/forge/fork/migration/helpers/MigrationForkTest.sol @@ -8,15 +8,15 @@ import {MorphoLib} from "../../../../../lib/morpho-blue/src/libraries/periphery/ import {Market} from "../../../../../lib/morpho-blue/src/interfaces/IMorpho.sol"; import {MorphoBalancesLib} from "../../../../../lib/morpho-blue/src/libraries/periphery/MorphoBalancesLib.sol"; -import "../../helpers/EthereumTest.sol"; -import {BaseBundler} from "../../../../../src/BaseBundler.sol"; +import "../../helpers/ForkTest.sol"; +import {CoreBundler} from "../../../../../src/CoreBundler.sol"; import {PermitBundler} from "../../../../../src/PermitBundler.sol"; import {Permit2Bundler} from "../../../../../src/Permit2Bundler.sol"; import {ERC4626Bundler} from "../../../../../src/ERC4626Bundler.sol"; import {MorphoBundler} from "../../../../../src/MorphoBundler.sol"; import {ERC4626Mock} from "../../../../../src/mocks/ERC4626Mock.sol"; -contract EthereumMigrationTest is EthereumTest { +contract MigrationForkTest is ForkTest { using SafeTransferLib for ERC20; using MarketParamsLib for MarketParams; using MorphoLib for IMorpho; diff --git a/test/forge/ethereum/migration/interfaces/IAToken.sol b/test/forge/fork/migration/interfaces/IAToken.sol similarity index 100% rename from test/forge/ethereum/migration/interfaces/IAToken.sol rename to test/forge/fork/migration/interfaces/IAToken.sol diff --git a/test/forge/helpers/BaseTest.sol b/test/forge/helpers/CommonTest.sol similarity index 95% rename from test/forge/helpers/BaseTest.sol rename to test/forge/helpers/CommonTest.sol index 884336f9..96abf492 100644 --- a/test/forge/helpers/BaseTest.sol +++ b/test/forge/helpers/CommonTest.sol @@ -26,13 +26,16 @@ import { import {IrmMock} from "../../../lib/morpho-blue/src/mocks/IrmMock.sol"; import {OracleMock} from "../../../lib/morpho-blue/src/mocks/OracleMock.sol"; +import {WETH} from "../../../lib/solmate/src/tokens/WETH.sol"; -import {BaseBundler} from "../../../src/BaseBundler.sol"; +import {CoreBundler} from "../../../src/CoreBundler.sol"; +import {PermitBundler} from "../../../src/PermitBundler.sol"; import {TransferBundler} from "../../../src/TransferBundler.sol"; import {ERC4626Bundler} from "../../../src/ERC4626Bundler.sol"; import {UrdBundler} from "../../../src/UrdBundler.sol"; import {MorphoBundler, Withdrawal} from "../../../src/MorphoBundler.sol"; import {ERC20WrapperBundler} from "../../../src/ERC20WrapperBundler.sol"; +import {AgnosticBundler} from "../../../src/mocks/AgnosticBundler.sol"; import "../../../lib/forge-std/src/Test.sol"; import "../../../lib/forge-std/src/console2.sol"; @@ -41,7 +44,7 @@ uint256 constant MIN_AMOUNT = 1000; uint256 constant MAX_AMOUNT = 2 ** 64; // Must be less than or equal to type(uint160).max. uint256 constant SIGNATURE_DEADLINE = type(uint32).max; -abstract contract BaseTest is Test { +abstract contract CommonTest is Test { using MathLib for uint256; using SharesMathLib for uint256; using MarketParamsLib for MarketParams; @@ -58,7 +61,7 @@ abstract contract BaseTest is Test { IrmMock internal irm; OracleMock internal oracle; - BaseBundler internal bundler; + CoreBundler internal bundler; bytes[] internal bundle; bytes[] internal callbackBundle; @@ -67,6 +70,8 @@ abstract contract BaseTest is Test { morpho = IMorpho(deployCode("Morpho.sol", abi.encode(OWNER))); vm.label(address(morpho), "Morpho"); + bundler = new AgnosticBundler(address(morpho), address(new WETH())); + irm = new IrmMock(); vm.startPrank(OWNER); diff --git a/test/forge/helpers/LocalTest.sol b/test/forge/helpers/LocalTest.sol index 10bdf4ff..d229d478 100644 --- a/test/forge/helpers/LocalTest.sol +++ b/test/forge/helpers/LocalTest.sol @@ -3,9 +3,9 @@ pragma solidity ^0.8.0; import {ERC20Mock} from "../../../src/mocks/ERC20Mock.sol"; -import "./BaseTest.sol"; +import "./CommonTest.sol"; -abstract contract LocalTest is BaseTest { +abstract contract LocalTest is CommonTest { using MathLib for uint256; using SharesMathLib for uint256; using MarketParamsLib for MarketParams;