From bfb95209fc8ab5ebac917f21f9edec5d730e58a4 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Thu, 14 Sep 2023 09:50:01 +0200 Subject: [PATCH 1/6] refactor(pragma): update interfaces pragma --- contracts/ethereum-mainnet/interfaces/IStEth.sol | 2 +- contracts/ethereum-mainnet/interfaces/IWStEth.sol | 2 +- contracts/interfaces/IMorphoBundler.sol | 2 +- contracts/interfaces/IMulticall.sol | 2 +- contracts/interfaces/IWNative.sol | 2 +- contracts/migration/interfaces/ICEth.sol | 2 +- contracts/migration/interfaces/ICToken.sol | 2 +- contracts/migration/interfaces/ICompoundV3.sol | 2 +- contracts/migration/interfaces/IComptroller.sol | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contracts/ethereum-mainnet/interfaces/IStEth.sol b/contracts/ethereum-mainnet/interfaces/IStEth.sol index d63efe7a..df6a9fae 100644 --- a/contracts/ethereum-mainnet/interfaces/IStEth.sol +++ b/contracts/ethereum-mainnet/interfaces/IStEth.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: AGPL-3.0-only -pragma solidity >=0.5.0; +pragma solidity >=0.6.2; interface IStEth { function transferShares(address _recipient, uint256 _sharesAmount) external returns (uint256); diff --git a/contracts/ethereum-mainnet/interfaces/IWStEth.sol b/contracts/ethereum-mainnet/interfaces/IWStEth.sol index 9e92cafd..f6d88f95 100644 --- a/contracts/ethereum-mainnet/interfaces/IWStEth.sol +++ b/contracts/ethereum-mainnet/interfaces/IWStEth.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.5.0; +pragma solidity >=0.6.2; interface IWStEth { function DOMAIN_SEPARATOR() external view returns (bytes32); diff --git a/contracts/interfaces/IMorphoBundler.sol b/contracts/interfaces/IMorphoBundler.sol index a421ee5d..082eb3dc 100644 --- a/contracts/interfaces/IMorphoBundler.sol +++ b/contracts/interfaces/IMorphoBundler.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.5.0; +pragma solidity >=0.6.2; import { IMorphoRepayCallback, diff --git a/contracts/interfaces/IMulticall.sol b/contracts/interfaces/IMulticall.sol index 115ef0fe..086a9190 100644 --- a/contracts/interfaces/IMulticall.sol +++ b/contracts/interfaces/IMulticall.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.5.0; +pragma solidity >=0.6.2; interface IMulticall { function multicall(uint256 deadline, bytes[] calldata data) external payable returns (bytes[] memory results); diff --git a/contracts/interfaces/IWNative.sol b/contracts/interfaces/IWNative.sol index 3e5f7d21..f41b6153 100644 --- a/contracts/interfaces/IWNative.sol +++ b/contracts/interfaces/IWNative.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.5.0; +pragma solidity >=0.6.2; interface IWNative { function deposit() external payable; diff --git a/contracts/migration/interfaces/ICEth.sol b/contracts/migration/interfaces/ICEth.sol index d8e3e4ee..cc072d33 100644 --- a/contracts/migration/interfaces/ICEth.sol +++ b/contracts/migration/interfaces/ICEth.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.5.0; +pragma solidity >=0.6.2; interface ICEth { function repayBorrowBehalf(address borrower) external payable; diff --git a/contracts/migration/interfaces/ICToken.sol b/contracts/migration/interfaces/ICToken.sol index c788c116..c8abf473 100644 --- a/contracts/migration/interfaces/ICToken.sol +++ b/contracts/migration/interfaces/ICToken.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.5.0; +pragma solidity >=0.6.2; interface ICToken { function underlying() external returns (address); diff --git a/contracts/migration/interfaces/ICompoundV3.sol b/contracts/migration/interfaces/ICompoundV3.sol index 76e5449b..d05356c2 100644 --- a/contracts/migration/interfaces/ICompoundV3.sol +++ b/contracts/migration/interfaces/ICompoundV3.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.5.0; +pragma solidity >=0.6.2; interface ICompoundV3 { function name() external view returns (string memory); diff --git a/contracts/migration/interfaces/IComptroller.sol b/contracts/migration/interfaces/IComptroller.sol index 4615a3cb..13ecd2c2 100644 --- a/contracts/migration/interfaces/IComptroller.sol +++ b/contracts/migration/interfaces/IComptroller.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.5.0; +pragma solidity >=0.6.2; interface IComptroller { function enterMarkets(address[] calldata cTokens) external returns (uint256[] memory); From 606099b6956ed14428a39cfaf64f57d0352193a0 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Thu, 14 Sep 2023 10:28:16 +0200 Subject: [PATCH 2/6] docs(bundler): add natspecs --- contracts/BaseBundler.sol | 7 +-- contracts/ERC4626Bundler.sol | 47 +++++++++++-------- contracts/MorphoBundler.sol | 35 +++++++------- contracts/Permit2Bundler.sol | 7 ++- contracts/WNativeBundler.sol | 6 ++- .../ethereum-mainnet/EthereumBundler.sol | 7 +-- contracts/ethereum-mainnet/StEthBundler.sol | 4 +- .../libraries/ConstantsLib.sol | 5 ++ .../migration/AaveV2MigrationBundler.sol | 12 +++-- .../migration/AaveV3MigrationBundler.sol | 15 ++++-- .../AaveV3OptimizerMigrationBundler.sol | 13 +++++ .../migration/CompoundV2MigrationBundler.sol | 24 ++++++---- .../migration/CompoundV3MigrationBundler.sol | 13 ++++- 13 files changed, 128 insertions(+), 67 deletions(-) create mode 100644 contracts/ethereum-mainnet/libraries/ConstantsLib.sol diff --git a/contracts/BaseBundler.sol b/contracts/BaseBundler.sol index 201e9adb..80024e83 100644 --- a/contracts/BaseBundler.sol +++ b/contracts/BaseBundler.sol @@ -33,8 +33,8 @@ abstract contract BaseBundler is BaseSelfMulticall, BaseCallbackReceiver { return _multicall(data); } - /// @dev Transfers the minimum between the given `amount` and the bundler's balance of `asset` from the bundler to - /// `recipient`. + /// @notice Transfers the minimum between the given `amount` and the bundler's balance of `asset` from the bundler + /// to `recipient`. function transfer(address asset, address recipient, uint256 amount) external payable { require(recipient != address(0), ErrorsLib.ZERO_ADDRESS); require(recipient != address(this), ErrorsLib.BUNDLER_ADDRESS); @@ -46,7 +46,8 @@ abstract contract BaseBundler is BaseSelfMulticall, BaseCallbackReceiver { ERC20(asset).safeTransfer(recipient, amount); } - /// @dev Transfers the minimum between the given `amount` and the bundler's balance of native asset from the bundler + /// @notice Transfers the minimum between the given `amount` and the bundler's balance of native asset from the + /// bundler /// to `recipient`. function transferNative(address recipient, uint256 amount) external payable { require(recipient != address(0), ErrorsLib.ZERO_ADDRESS); diff --git a/contracts/ERC4626Bundler.sol b/contracts/ERC4626Bundler.sol index 31965530..8249531a 100644 --- a/contracts/ERC4626Bundler.sol +++ b/contracts/ERC4626Bundler.sol @@ -18,51 +18,58 @@ abstract contract ERC4626Bundler is BaseBundler { /* ACTIONS */ - function mint(address vault, uint256 shares, address receiver) external payable { - require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); + /// @notice Mints the given amount of `shares` on the given ERC4626 `vault`, on behalf of `owner`. + function erc4626Mint(address vault, uint256 shares, address owner) external payable { + require(owner != address(0), ErrorsLib.ZERO_ADDRESS); address asset = IERC4626(vault).asset(); - uint256 amount = Math.min(IERC4626(vault).maxDeposit(receiver), ERC20(asset).balanceOf(address(this))); + uint256 assets = Math.min(IERC4626(vault).maxDeposit(owner), ERC20(asset).balanceOf(address(this))); - shares = Math.min(shares, IERC4626(vault).previewDeposit(amount)); - amount = IERC4626(vault).previewMint(shares); + shares = Math.min(shares, IERC4626(vault).previewDeposit(assets)); + assets = IERC4626(vault).previewMint(shares); - require(amount != 0, ErrorsLib.ZERO_AMOUNT); + require(assets != 0, ErrorsLib.ZERO_AMOUNT); // Approve 0 first to comply with tokens that implement the anti frontrunning approval fix. ERC20(asset).safeApprove(vault, 0); - ERC20(asset).safeApprove(vault, amount); - IERC4626(vault).mint(shares, receiver); + ERC20(asset).safeApprove(vault, assets); + IERC4626(vault).mint(shares, owner); } - function deposit(address vault, uint256 amount, address receiver) external payable { - require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); + /// @notice Deposits the given amount of `assets` on the given ERC4626 `vault`, on behalf of `owner`. + function erc4626Deposit(address vault, uint256 assets, address owner) external payable { + require(owner != address(0), ErrorsLib.ZERO_ADDRESS); address asset = IERC4626(vault).asset(); - amount = Math.min(amount, IERC4626(vault).maxDeposit(receiver)); - amount = Math.min(amount, ERC20(asset).balanceOf(address(this))); + assets = Math.min(assets, IERC4626(vault).maxDeposit(owner)); + assets = Math.min(assets, ERC20(asset).balanceOf(address(this))); - require(amount != 0, ErrorsLib.ZERO_AMOUNT); + require(assets != 0, ErrorsLib.ZERO_AMOUNT); // Approve 0 first to comply with tokens that implement the anti frontrunning approval fix. ERC20(asset).safeApprove(vault, 0); - ERC20(asset).safeApprove(vault, amount); - IERC4626(vault).deposit(amount, receiver); + ERC20(asset).safeApprove(vault, assets); + IERC4626(vault).deposit(assets, owner); } - function withdraw(address vault, uint256 amount, address receiver) external payable { + /// @notice Withdraws the given amount of `assets` from the given ERC4626 `vault`, transferring assets to + /// `receiver`. + /// @notice Warning: should only be called via the bundler's `multicall` function. + function erc4626Withdraw(address vault, uint256 assets, address receiver) external payable { require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); address initiator = _initiator; - amount = Math.min(amount, IERC4626(vault).maxWithdraw(initiator)); + assets = Math.min(assets, IERC4626(vault).maxWithdraw(initiator)); - require(amount != 0, ErrorsLib.ZERO_AMOUNT); + require(assets != 0, ErrorsLib.ZERO_AMOUNT); - IERC4626(vault).withdraw(amount, receiver, initiator); + IERC4626(vault).withdraw(assets, receiver, initiator); } - function redeem(address vault, uint256 shares, address receiver) external payable { + /// @notice Redeems the given amount of `shares` from the given ERC4626 `vault`, transferring assets to `receiver`. + /// @notice Warning: should only be called via the bundler's `multicall` function. + function erc4626Redeem(address vault, uint256 shares, address receiver) external payable { require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); address initiator = _initiator; diff --git a/contracts/MorphoBundler.sol b/contracts/MorphoBundler.sol index 74b66c2a..8cd8d536 100644 --- a/contracts/MorphoBundler.sol +++ b/contracts/MorphoBundler.sol @@ -55,7 +55,7 @@ abstract contract MorphoBundler is BaseBundler, IMorphoBundler { /* ACTIONS */ - /// @dev Approves this contract to manage the `authorization.authorizer`'s position via EIP712 `signature`. + /// @notice Approves this contract to manage the `authorization.authorizer`'s position via EIP712 `signature`. function morphoSetAuthorizationWithSig(Authorization calldata authorization, Signature calldata signature) external payable @@ -63,9 +63,9 @@ abstract contract MorphoBundler is BaseBundler, IMorphoBundler { MORPHO.setAuthorizationWithSig(authorization, signature); } - /// @dev Supplies `amount` of `asset` of `onBehalf` using permit2 in a single tx. - /// The supplied amount cannot be used as collateral but is eligible to earn interest. - /// Note: pass `amount = type(uint256).max` to supply the bundler's borrowable asset balance. + /// @notice Supplies `amount` of `asset` of `onBehalf` using permit2 in a single tx. + /// @notice The supplied amount cannot be used as collateral but is eligible to earn interest. + /// @dev Pass `amount = type(uint256).max` to supply the bundler's borrowable asset balance. function morphoSupply( MarketParams calldata marketparams, uint256 amount, @@ -85,8 +85,8 @@ abstract contract MorphoBundler is BaseBundler, IMorphoBundler { MORPHO.supply(marketparams, amount, shares, onBehalf, data); } - /// @dev Supplies `amount` of `asset` collateral to the pool on behalf of `onBehalf`. - /// Note: pass `amount = type(uint256).max` to supply the bundler's collateral asset balance. + /// @notice Supplies `amount` of `asset` collateral to the pool on behalf of `onBehalf`. + /// @dev Pass `amount = type(uint256).max` to supply the bundler's collateral asset balance. function morphoSupplyCollateral( MarketParams calldata marketparams, uint256 amount, @@ -105,8 +105,9 @@ abstract contract MorphoBundler is BaseBundler, IMorphoBundler { MORPHO.supplyCollateral(marketparams, amount, onBehalf, data); } - /// @dev Borrows `amount` of `asset` on behalf of the sender. Sender must have previously approved the bundler as - /// their manager on Blue. + /// @notice Borrows `amount` of `asset` on behalf of the sender. + /// @notice Warning: should only be called via the bundler's `multicall` function. + /// @dev Initiator must have previously authorized the bundler to act on their behalf on Blue. function morphoBorrow(MarketParams calldata marketparams, uint256 amount, uint256 shares, address receiver) external payable @@ -114,8 +115,8 @@ abstract contract MorphoBundler is BaseBundler, IMorphoBundler { MORPHO.borrow(marketparams, amount, shares, _initiator, receiver); } - /// @dev Repays `amount` of `asset` on behalf of `onBehalf`. - /// Note: pass `amount = type(uint256).max` to repay the bundler's borrowable asset balance. + /// @notice Repays `amount` of `asset` on behalf of `onBehalf`. + /// @dev Pass `amount = type(uint256).max` to repay the bundler's borrowable asset balance. function morphoRepay( MarketParams calldata marketparams, uint256 amount, @@ -135,8 +136,9 @@ abstract contract MorphoBundler is BaseBundler, IMorphoBundler { MORPHO.repay(marketparams, amount, shares, onBehalf, data); } - /// @dev Withdraws `amount` of the borrowable asset on behalf of `onBehalf`. Sender must have previously authorized - /// the bundler to act on their behalf on Blue. + /// @notice Withdraws `amount` of the borrowable asset on behalf of `onBehalf`. + /// @notice Warning: should only be called via the bundler's `multicall` function. + /// @dev Initiator must have previously authorized the bundler to act on their behalf on Blue. function morphoWithdraw(MarketParams calldata marketparams, uint256 amount, uint256 shares, address receiver) external payable @@ -144,8 +146,9 @@ abstract contract MorphoBundler is BaseBundler, IMorphoBundler { MORPHO.withdraw(marketparams, amount, shares, _initiator, receiver); } - /// @dev Withdraws `amount` of the collateral asset on behalf of sender. Sender must have previously authorized the - /// bundler to act on their behalf on Blue. + /// @notice Withdraws `amount` of the collateral asset on behalf of sender. + /// @notice Warning: should only be called via the bundler's `multicall` function. + /// @dev Initiator must have previously authorized the bundler to act on their behalf on Blue. function morphoWithdrawCollateral(MarketParams calldata marketparams, uint256 amount, address receiver) external payable @@ -153,7 +156,7 @@ abstract contract MorphoBundler is BaseBundler, IMorphoBundler { MORPHO.withdrawCollateral(marketparams, amount, _initiator, receiver); } - /// @dev Triggers a liquidation on Blue. + /// @notice Triggers a liquidation on Blue. function morphoLiquidate( MarketParams calldata marketparams, address borrower, @@ -166,7 +169,7 @@ abstract contract MorphoBundler is BaseBundler, IMorphoBundler { MORPHO.liquidate(marketparams, borrower, seizedAssets, repaidShares, data); } - /// @dev Triggers a flash loan on Blue. + /// @notice Triggers a flash loan on Blue. function morphoFlashLoan(address asset, uint256 amount, bytes calldata data) external payable { _approveMaxBlue(asset); diff --git a/contracts/Permit2Bundler.sol b/contracts/Permit2Bundler.sol index 23c5cedd..3f18ab5f 100644 --- a/contracts/Permit2Bundler.sol +++ b/contracts/Permit2Bundler.sol @@ -18,16 +18,19 @@ abstract contract Permit2Bundler is BaseBundler { /* ACTIONS */ - /// @dev Approves the given `amount` of `asset` from sender to be spent by this contract via Permit2 with the given + /// @notice Approves the given `amount` of `asset` from sender to be spent by this contract via Permit2 with the + /// given /// `deadline` & EIP712 `signature`. + /// Should only be called via the bundler's `multicall` function. function approve2(address asset, uint256 amount, uint256 deadline, Signature calldata signature) external payable { require(amount != 0, ErrorsLib.ZERO_AMOUNT); ERC20(asset).simplePermit2(_initiator, address(this), amount, deadline, signature.v, signature.r, signature.s); } - /// @dev Transfers the given `amount` of `asset` from sender to this contract via ERC20 transfer with Permit2 + /// @notice Transfers the given `amount` of `asset` from sender to this contract via ERC20 transfer with Permit2 /// fallback. + /// Should only be called via the bundler's `multicall` function. function transferFrom2(address asset, uint256 amount) external payable { require(amount != 0, ErrorsLib.ZERO_AMOUNT); diff --git a/contracts/WNativeBundler.sol b/contracts/WNativeBundler.sol index 2c8fac7c..9fa2d859 100644 --- a/contracts/WNativeBundler.sol +++ b/contracts/WNativeBundler.sol @@ -38,7 +38,8 @@ abstract contract WNativeBundler is BaseBundler { /* ACTIONS */ - /// @dev Wraps the given `amount` of the native token to wNative and transfers it to `receiver`. + /// @notice Wraps the given `amount` of the native token to wNative and transfers it to `receiver`. + /// @notice Warning: should only be called via the bundler's `multicall` function. function wrapNative(uint256 amount, address receiver) external payable { require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); @@ -51,7 +52,8 @@ abstract contract WNativeBundler is BaseBundler { if (receiver != address(this)) ERC20(WRAPPED_NATIVE).safeTransfer(receiver, amount); } - /// @dev Unwraps the given `amount` of wNative to the native token and transfers it to `receiver`. + /// @notice Unwraps the given `amount` of wNative to the native token and transfers it to `receiver`. + /// @notice Warning: should only be called via the bundler's `multicall` function. function unwrapNative(uint256 amount, address receiver) external payable { require(receiver != address(this), ErrorsLib.BUNDLER_ADDRESS); require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); diff --git a/contracts/ethereum-mainnet/EthereumBundler.sol b/contracts/ethereum-mainnet/EthereumBundler.sol index 21e0deb8..ccd5a68b 100644 --- a/contracts/ethereum-mainnet/EthereumBundler.sol +++ b/contracts/ethereum-mainnet/EthereumBundler.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.21; +import "./libraries/ConstantsLib.sol"; + import {EVMBundler} from "../EVMBundler.sol"; import {StEthBundler} from "./StEthBundler.sol"; import {WNativeBundler} from "../WNativeBundler.sol"; @@ -10,11 +12,6 @@ import {WNativeBundler} from "../WNativeBundler.sol"; /// @custom:contact security@morpho.org /// @notice Bundler contract specific to the Ethereum mainnet. contract EthereumBundler is EVMBundler, WNativeBundler, StEthBundler { - /* CONSTANTS */ - - /// @dev The address of the WETH contract on Ethereum mainnet. - address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - /* CONSTRUCTOR */ constructor(address morpho) EVMBundler(morpho) WNativeBundler(WETH) {} diff --git a/contracts/ethereum-mainnet/StEthBundler.sol b/contracts/ethereum-mainnet/StEthBundler.sol index c8713f26..6cbf9946 100644 --- a/contracts/ethereum-mainnet/StEthBundler.sol +++ b/contracts/ethereum-mainnet/StEthBundler.sol @@ -33,7 +33,7 @@ abstract contract StEthBundler is BaseBundler { /* ACTIONS */ - /// @dev Wraps the given `amount` of stETH to wstETH and transfers it to `receiver`. + /// @notice Wraps the given `amount` of stETH to wstETH and transfers it to `receiver`. function wrapStEth(uint256 amount, address receiver) external payable { require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); @@ -46,7 +46,7 @@ abstract contract StEthBundler is BaseBundler { if (receiver != address(this)) ERC20(WST_ETH).safeTransfer(receiver, amount); } - /// @dev Unwraps the given `amount` of wstETH to stETH and transfers it to `receiver`. + /// @notice Unwraps the given `amount` of wstETH to stETH and transfers it to `receiver`. function unwrapStEth(uint256 amount, address receiver) external payable { require(receiver != address(this), ErrorsLib.BUNDLER_ADDRESS); require(receiver != address(0), ErrorsLib.ZERO_ADDRESS); diff --git a/contracts/ethereum-mainnet/libraries/ConstantsLib.sol b/contracts/ethereum-mainnet/libraries/ConstantsLib.sol new file mode 100644 index 00000000..213993e2 --- /dev/null +++ b/contracts/ethereum-mainnet/libraries/ConstantsLib.sol @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity ^0.8.0; + +/// @dev The address of the WETH contract on Ethereum mainnet. +address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; diff --git a/contracts/migration/AaveV2MigrationBundler.sol b/contracts/migration/AaveV2MigrationBundler.sol index 96f6c814..2e969b64 100644 --- a/contracts/migration/AaveV2MigrationBundler.sol +++ b/contracts/migration/AaveV2MigrationBundler.sol @@ -23,13 +23,17 @@ contract AaveV2MigrationBundler is MigrationBundler, Permit2Bundler { /* ACTIONS */ - function aaveV2Withdraw(address asset, uint256 amount, address to) external payable { - AAVE_V2_POOl.withdraw(asset, amount, to); - } - + /// @notice Repays `amount` of `asset` on AaveV2, on behalf of the initiator. + /// @notice Warning: should only be called via the bundler's `multicall` function. function aaveV2Repay(address asset, uint256 amount, uint256 rateMode) external payable { _approveMaxTo(asset, address(AAVE_V2_POOl)); AAVE_V2_POOl.repay(asset, amount, rateMode, _initiator); } + + /// @notice Withdraws `amount` of `asset` on AaveV3, on behalf of the initiator, transferring funds to `receiver`. + /// @dev Initiator must have previously transferred their aTokens to the bundler. + function aaveV2Withdraw(address asset, uint256 amount, address receiver) external payable { + AAVE_V2_POOl.withdraw(asset, amount, receiver); + } } diff --git a/contracts/migration/AaveV3MigrationBundler.sol b/contracts/migration/AaveV3MigrationBundler.sol index c6dc5352..aabc1280 100644 --- a/contracts/migration/AaveV3MigrationBundler.sol +++ b/contracts/migration/AaveV3MigrationBundler.sol @@ -24,16 +24,23 @@ contract AaveV3MigrationBundler is MigrationBundler, Permit2Bundler { /* ACTIONS */ - function aaveV3Withdraw(address asset, uint256 amount, address to) external payable { - AAVE_V3_POOL.withdraw(asset, amount, to); - } - + /// @notice Repays `amount` of `asset` on AaveV3, on behalf of the initiator. + /// @notice Warning: should only be called via the bundler's `multicall` function. function aaveV3Repay(address asset, uint256 amount, uint256 interestRateMode) external payable { _approveMaxTo(asset, address(AAVE_V3_POOL)); AAVE_V3_POOL.repay(asset, amount, interestRateMode, _initiator); } + /// @notice Withdraws `amount` of `asset` on AaveV3, on behalf of the initiator, transferring funds to `receiver`. + /// @dev Initiator must have previously transferred their aTokens to the bundler. + function aaveV3Withdraw(address asset, uint256 amount, address to) external payable { + AAVE_V3_POOL.withdraw(asset, amount, to); + } + + /// @notice Approves the bundler to manage the initiator's `aToken` balance, given a signed EIP-2612 approval + /// message. + /// @notice Warning: should only be called via the bundler's `multicall` function. function aaveV3PermitAToken(address aToken, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external payable diff --git a/contracts/migration/AaveV3OptimizerMigrationBundler.sol b/contracts/migration/AaveV3OptimizerMigrationBundler.sol index 2e711866..bb829548 100644 --- a/contracts/migration/AaveV3OptimizerMigrationBundler.sol +++ b/contracts/migration/AaveV3OptimizerMigrationBundler.sol @@ -24,12 +24,18 @@ contract AaveV3OptimizerMigrationBundler is MigrationBundler { /* ACTIONS */ + /// @notice Repays `amount` of `underlying` on the AaveV3 Optimizer, on behalf of the initiator. + /// @notice Warning: should only be called via the bundler's `multicall` function. function aaveV3OptimizerRepay(address underlying, uint256 amount) external payable { _approveMaxTo(underlying, address(AAVE_V3_OPTIMIZER)); AAVE_V3_OPTIMIZER.repay(underlying, amount, _initiator); } + /// @notice Repays `amount` of `underlying` on the AaveV3 Optimizer, on behalf of the initiator, transferring funds + /// to `receiver`. + /// @notice Warning: should only be called via the bundler's `multicall` function. + /// @dev Initiator must have previously approved the bundler to manage their AaveV3 Optimizer position. function aaveV3OptimizerWithdraw(address underlying, uint256 amount, address receiver, uint256 maxIterations) external payable @@ -37,10 +43,17 @@ contract AaveV3OptimizerMigrationBundler is MigrationBundler { AAVE_V3_OPTIMIZER.withdraw(underlying, amount, _initiator, receiver, maxIterations); } + /// @notice Repays `amount` of `underlying` on the AaveV3 Optimizer, on behalf of the initiator, transferring funds + /// to `receiver`. + /// @notice Warning: should only be called via the bundler's `multicall` function. + /// @dev Initiator must have previously approved the bundler to manage their AaveV3 Optimizer position. function aaveV3OptimizerWithdrawCollateral(address underlying, uint256 amount, address receiver) external payable { AAVE_V3_OPTIMIZER.withdrawCollateral(underlying, amount, _initiator, receiver); } + /// @notice Approves the bundler to act on behalf of the initiator on the AaveV3 Optimizer, given a signed EIP-712 + /// approval message. + /// @notice Warning: should only be called via the bundler's `multicall` function. function aaveV3OptimizerApproveManagerWithSig( bool isAllowed, uint256 nonce, diff --git a/contracts/migration/CompoundV2MigrationBundler.sol b/contracts/migration/CompoundV2MigrationBundler.sol index 348d94b7..9b7aa46e 100644 --- a/contracts/migration/CompoundV2MigrationBundler.sol +++ b/contracts/migration/CompoundV2MigrationBundler.sol @@ -27,31 +27,39 @@ contract CompoundV2MigrationBundler is MigrationBundler, Permit2Bundler { C_NATIVE = ICEth(cNative); } + /* CALLBACKS */ + + /// @dev Only the wNative contract or CompoundV2 is allowed to transfer the native token to this contract, without + /// any calldata. + receive() external payable { + require(msg.sender == address(WRAPPED_NATIVE) || msg.sender == address(C_NATIVE), ErrorsLib.UNAUTHORIZED_SENDER); + } + /* ACTIONS */ - function compoundV2Repay(address cToken, uint256 repayAmount) external payable { + /// @notice Repays `amount` of `cToken`'s underlying asset, on behalf of the initiator. + /// @notice Warning: should only be called via the bundler's `multicall` function. + function compoundV2Repay(address cToken, uint256 amount) external payable { if (cToken == address(C_NATIVE)) { - WRAPPED_NATIVE.withdraw(repayAmount); + WRAPPED_NATIVE.withdraw(amount); // Reverts in case of error. - C_NATIVE.repayBorrowBehalf{value: repayAmount}(_initiator); + C_NATIVE.repayBorrowBehalf{value: amount}(_initiator); } else { _approveMaxTo(ICToken(cToken).underlying(), cToken); // Doesn't revert in case of error. - uint256 err = ICToken(cToken).repayBorrowBehalf(_initiator, repayAmount); + uint256 err = ICToken(cToken).repayBorrowBehalf(_initiator, amount); require(err == 0, ErrorsLib.REPAY_ERROR); } } + /// @notice Redeems `amount` of `cToken`'s underlying asset from CompoundV2. + /// @dev Initiator must have previously transferred their cTokens to the bundler. function compoundV2Redeem(address cToken, uint256 amount) external payable { uint256 err = ICToken(cToken).redeemUnderlying(amount); require(err == 0, ErrorsLib.REDEEM_ERROR); if (cToken == address(C_NATIVE)) WRAPPED_NATIVE.deposit{value: amount}(); } - - receive() external payable { - require(msg.sender == address(WRAPPED_NATIVE) || msg.sender == address(C_NATIVE), ErrorsLib.UNAUTHORIZED_SENDER); - } } diff --git a/contracts/migration/CompoundV3MigrationBundler.sol b/contracts/migration/CompoundV3MigrationBundler.sol index b0cfafd2..d12b5f60 100644 --- a/contracts/migration/CompoundV3MigrationBundler.sol +++ b/contracts/migration/CompoundV3MigrationBundler.sol @@ -17,20 +17,31 @@ contract CompoundV3MigrationBundler is MigrationBundler, Permit2Bundler { /* ACTIONS */ - function compoundV3Supply(address instance, address asset, uint256 amount) external payable { + /// @notice Repays `amount` of `asset` on the CompoundV3 `instance`, on behalf of the initiator. + /// @notice Warning: should only be called via the bundler's `multicall` function. + function compoundV3Repay(address instance, address asset, uint256 amount) external payable { _approveMaxTo(asset, instance); + // Compound V3 uses signed accounting: supplying to a negative balance actually repays the borrow position. ICompoundV3(instance).supplyTo(_initiator, asset, amount); } + /// @notice Withdraws `amount` of `asset` on the CompoundV3 `instance`. + /// @dev Initiator must have previously transferred their CompoundV3 position to the bundler. function compoundV3Withdraw(address instance, address asset, uint256 amount) external payable { ICompoundV3(instance).withdraw(asset, amount); } + /// @notice Withdraws `amount` of `asset` from the CompoundV3 `instance`, on behalf of the initiator. + /// @notice Warning: should only be called via the bundler's `multicall` function. + /// @dev Initiator must have previously approved the bundler to manage their CompoundV3 position. function compoundV3WithdrawFrom(address instance, address to, address asset, uint256 amount) external payable { ICompoundV3(instance).withdrawFrom(_initiator, to, asset, amount); } + /// @notice Approves the bundler to act on behalf of the initiator on the CompoundV3 `instance`, given a signed + /// EIP-712 approval message. + /// @notice Warning: should only be called via the bundler's `multicall` function. function compoundV3AllowBySig( address instance, bool isAllowed, From 14f8669198d1cb2c27fa6d05e46b2127c2fbd7d3 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Thu, 14 Sep 2023 11:00:29 +0200 Subject: [PATCH 3/6] fix(ts): add migration bundlers --- .../migration/AaveV2MigrationBundler.sol | 4 +- .../migration/AaveV3MigrationBundler.sol | 4 +- .../AaveV3OptimizerMigrationBundler.sol | 4 +- .../migration/CompoundV3MigrationBundler.sol | 4 +- src/BundlerAction.ts | 158 ++++++++++++++++-- 5 files changed, 155 insertions(+), 19 deletions(-) diff --git a/contracts/migration/AaveV2MigrationBundler.sol b/contracts/migration/AaveV2MigrationBundler.sol index 2e969b64..668b596e 100644 --- a/contracts/migration/AaveV2MigrationBundler.sol +++ b/contracts/migration/AaveV2MigrationBundler.sol @@ -25,10 +25,10 @@ contract AaveV2MigrationBundler is MigrationBundler, Permit2Bundler { /// @notice Repays `amount` of `asset` on AaveV2, on behalf of the initiator. /// @notice Warning: should only be called via the bundler's `multicall` function. - function aaveV2Repay(address asset, uint256 amount, uint256 rateMode) external payable { + function aaveV2Repay(address asset, uint256 amount, uint256 interestRateMode) external payable { _approveMaxTo(asset, address(AAVE_V2_POOl)); - AAVE_V2_POOl.repay(asset, amount, rateMode, _initiator); + AAVE_V2_POOl.repay(asset, amount, interestRateMode, _initiator); } /// @notice Withdraws `amount` of `asset` on AaveV3, on behalf of the initiator, transferring funds to `receiver`. diff --git a/contracts/migration/AaveV3MigrationBundler.sol b/contracts/migration/AaveV3MigrationBundler.sol index aabc1280..887d0730 100644 --- a/contracts/migration/AaveV3MigrationBundler.sol +++ b/contracts/migration/AaveV3MigrationBundler.sol @@ -34,8 +34,8 @@ contract AaveV3MigrationBundler is MigrationBundler, Permit2Bundler { /// @notice Withdraws `amount` of `asset` on AaveV3, on behalf of the initiator, transferring funds to `receiver`. /// @dev Initiator must have previously transferred their aTokens to the bundler. - function aaveV3Withdraw(address asset, uint256 amount, address to) external payable { - AAVE_V3_POOL.withdraw(asset, amount, to); + function aaveV3Withdraw(address asset, uint256 amount, address receiver) external payable { + AAVE_V3_POOL.withdraw(asset, amount, receiver); } /// @notice Approves the bundler to manage the initiator's `aToken` balance, given a signed EIP-2612 approval diff --git a/contracts/migration/AaveV3OptimizerMigrationBundler.sol b/contracts/migration/AaveV3OptimizerMigrationBundler.sol index bb829548..128cfdfd 100644 --- a/contracts/migration/AaveV3OptimizerMigrationBundler.sol +++ b/contracts/migration/AaveV3OptimizerMigrationBundler.sol @@ -55,11 +55,11 @@ contract AaveV3OptimizerMigrationBundler is MigrationBundler { /// approval message. /// @notice Warning: should only be called via the bundler's `multicall` function. function aaveV3OptimizerApproveManagerWithSig( - bool isAllowed, + bool isApproved, uint256 nonce, uint256 deadline, Types.Signature calldata signature ) external payable { - AAVE_V3_OPTIMIZER.approveManagerWithSig(_initiator, address(this), isAllowed, nonce, deadline, signature); + AAVE_V3_OPTIMIZER.approveManagerWithSig(_initiator, address(this), isApproved, nonce, deadline, signature); } } diff --git a/contracts/migration/CompoundV3MigrationBundler.sol b/contracts/migration/CompoundV3MigrationBundler.sol index d12b5f60..be3cfe32 100644 --- a/contracts/migration/CompoundV3MigrationBundler.sol +++ b/contracts/migration/CompoundV3MigrationBundler.sol @@ -35,8 +35,8 @@ contract CompoundV3MigrationBundler is MigrationBundler, Permit2Bundler { /// @notice Withdraws `amount` of `asset` from the CompoundV3 `instance`, on behalf of the initiator. /// @notice Warning: should only be called via the bundler's `multicall` function. /// @dev Initiator must have previously approved the bundler to manage their CompoundV3 position. - function compoundV3WithdrawFrom(address instance, address to, address asset, uint256 amount) external payable { - ICompoundV3(instance).withdrawFrom(_initiator, to, asset, amount); + function compoundV3WithdrawFrom(ICompoundV3 instance, address asset, uint256 amount) external payable { + ICompoundV3(instance).withdrawFrom(_initiator, address(this), asset, amount); } /// @notice Approves the bundler to act on behalf of the initiator on the CompoundV3 `instance`, given a signed diff --git a/src/BundlerAction.ts b/src/BundlerAction.ts index 7e7f40e3..82a6cbdb 100644 --- a/src/BundlerAction.ts +++ b/src/BundlerAction.ts @@ -1,13 +1,18 @@ import { BigNumberish, Signature } from "ethers"; import { + AaveV2MigrationBundler__factory, + AaveV3MigrationBundler__factory, + AaveV3OptimizerMigrationBundler__factory, BaseBundler__factory, + CompoundV2MigrationBundler__factory, + CompoundV3MigrationBundler__factory, ERC4626Bundler__factory, MorphoBundler__factory, Permit2Bundler__factory, StEthBundler__factory, WNativeBundler__factory, } from "types"; -import { AuthorizationStruct, MarketParamsStruct, SignatureStruct } from "types/contracts/MorphoBundler"; +import { AuthorizationStruct, MarketParamsStruct } from "types/contracts/MorphoBundler"; export type BundlerCall = string; @@ -18,6 +23,11 @@ export class BundlerAction { private static MORPHO_BUNDLER_IFC = MorphoBundler__factory.createInterface(); private static WNATIVE_BUNDLER_IFC = WNativeBundler__factory.createInterface(); private static ST_ETH_BUNDLER_IFC = StEthBundler__factory.createInterface(); + private static AAVE_V2_BUNDLER_IFC = AaveV2MigrationBundler__factory.createInterface(); + private static AAVE_V3_BUNDLER_IFC = AaveV3MigrationBundler__factory.createInterface(); + private static AAVE_V3_OPTIMIZER_BUNDLER_IFC = AaveV3OptimizerMigrationBundler__factory.createInterface(); + private static COMPOUND_V2_BUNDLER_IFC = CompoundV2MigrationBundler__factory.createInterface(); + private static COMPOUND_V3_BUNDLER_IFC = CompoundV3MigrationBundler__factory.createInterface(); /* ERC20 */ @@ -25,6 +35,8 @@ export class BundlerAction { return BundlerAction.BASE_BUNDLER_IFC.encodeFunctionData("transfer", [asset, recipient, amount]); } + /* Permit2 */ + static transferNative(recipient: string, amount: BigNumberish): BundlerCall { return BundlerAction.BASE_BUNDLER_IFC.encodeFunctionData("transferNative", [recipient, amount]); } @@ -44,28 +56,28 @@ export class BundlerAction { /* ERC4626 */ - static mint(erc4626: string, amount: BigNumberish, receiver: string): BundlerCall { - return BundlerAction.ERC4626_BUNDLER_IFC.encodeFunctionData("mint", [erc4626, amount, receiver]); + static erc4626Mint(erc4626: string, amount: BigNumberish, receiver: string): BundlerCall { + return BundlerAction.ERC4626_BUNDLER_IFC.encodeFunctionData("erc4626Mint", [erc4626, amount, receiver]); } - static deposit(erc4626: string, amount: BigNumberish, receiver: string): BundlerCall { - return BundlerAction.ERC4626_BUNDLER_IFC.encodeFunctionData("deposit", [erc4626, amount, receiver]); + static erc4626Deposit(erc4626: string, amount: BigNumberish, receiver: string): BundlerCall { + return BundlerAction.ERC4626_BUNDLER_IFC.encodeFunctionData("erc4626Deposit", [erc4626, amount, receiver]); } - static withdraw(erc4626: string, amount: BigNumberish, receiver: string): BundlerCall { - return BundlerAction.ERC4626_BUNDLER_IFC.encodeFunctionData("withdraw", [erc4626, amount, receiver]); + static erc4626Withdraw(erc4626: string, amount: BigNumberish, receiver: string): BundlerCall { + return BundlerAction.ERC4626_BUNDLER_IFC.encodeFunctionData("erc4626Withdraw", [erc4626, amount, receiver]); } - static redeem(erc4626: string, amount: BigNumberish, receiver: string): BundlerCall { - return BundlerAction.ERC4626_BUNDLER_IFC.encodeFunctionData("redeem", [erc4626, amount, receiver]); + static erc4626Redeem(erc4626: string, amount: BigNumberish, receiver: string): BundlerCall { + return BundlerAction.ERC4626_BUNDLER_IFC.encodeFunctionData("erc4626Redeem", [erc4626, amount, receiver]); } /* Morpho */ - static morphoSetAuthorizationWithSig(authorization: AuthorizationStruct, signature: SignatureStruct): BundlerCall { + static morphoSetAuthorizationWithSig(authorization: AuthorizationStruct, signature: Signature): BundlerCall { return BundlerAction.MORPHO_BUNDLER_IFC.encodeFunctionData("morphoSetAuthorizationWithSig", [ authorization, - signature, + { v: signature.v, r: signature.r, s: signature.s }, ]); } @@ -180,6 +192,130 @@ export class BundlerAction { static unwrapStEth(amount: BigNumberish, receiver: string): BundlerCall { return BundlerAction.ST_ETH_BUNDLER_IFC.encodeFunctionData("unwrapStEth", [amount, receiver]); } + + /* AaveV2 */ + + static aaveV2Repay(asset: string, amount: BigNumberish, rateMode: BigNumberish): BundlerCall { + return BundlerAction.AAVE_V2_BUNDLER_IFC.encodeFunctionData("aaveV2Repay", [asset, amount, rateMode]); + } + + static aaveV2Withdraw(asset: string, amount: BigNumberish, receiver: string): BundlerCall { + return BundlerAction.AAVE_V2_BUNDLER_IFC.encodeFunctionData("aaveV2Withdraw", [asset, amount, receiver]); + } + + /* AaveV3 */ + + static aaveV3Repay(asset: string, amount: BigNumberish, rateMode: BigNumberish): BundlerCall { + return BundlerAction.AAVE_V3_BUNDLER_IFC.encodeFunctionData("aaveV3Repay", [asset, amount, rateMode]); + } + + static aaveV3Withdraw(asset: string, amount: BigNumberish, receiver: string): BundlerCall { + return BundlerAction.AAVE_V3_BUNDLER_IFC.encodeFunctionData("aaveV3Withdraw", [asset, amount, receiver]); + } + + static aaveV3PermitAToken( + aToken: string, + value: BigNumberish, + deadline: BigNumberish, + signature: Signature, + ): BundlerCall { + return BundlerAction.AAVE_V3_BUNDLER_IFC.encodeFunctionData("aaveV3PermitAToken", [ + aToken, + value, + deadline, + signature.v, + signature.r, + signature.s, + ]); + } + + /* AaveV3 Optimizer */ + + static aaveV3OptimizerRepay(underlying: string, amount: BigNumberish): BundlerCall { + return BundlerAction.AAVE_V3_OPTIMIZER_BUNDLER_IFC.encodeFunctionData("aaveV3OptimizerRepay", [underlying, amount]); + } + + static aaveV3OptimizerWithdraw( + underlying: string, + amount: BigNumberish, + receiver: string, + maxIterations: BigNumberish, + ): BundlerCall { + return BundlerAction.AAVE_V3_OPTIMIZER_BUNDLER_IFC.encodeFunctionData("aaveV3OptimizerWithdraw", [ + underlying, + amount, + receiver, + maxIterations, + ]); + } + + static aaveV3OptimizerWithdrawCollateral(underlying: string, amount: BigNumberish, receiver: string): BundlerCall { + return BundlerAction.AAVE_V3_OPTIMIZER_BUNDLER_IFC.encodeFunctionData("aaveV3OptimizerWithdrawCollateral", [ + underlying, + amount, + receiver, + ]); + } + + static aaveV3OptimizerApproveManagerWithSig( + isApproved: boolean, + nonce: BigNumberish, + deadline: BigNumberish, + signature: Signature, + ): BundlerCall { + return BundlerAction.AAVE_V3_OPTIMIZER_BUNDLER_IFC.encodeFunctionData("aaveV3OptimizerApproveManagerWithSig", [ + isApproved, + nonce, + deadline, + { v: signature.v, r: signature.r, s: signature.s }, + ]); + } + + /* CompoundV2 */ + + static compoundV2Repay(cToken: string, amount: BigNumberish): BundlerCall { + return BundlerAction.COMPOUND_V2_BUNDLER_IFC.encodeFunctionData("compoundV2Repay", [cToken, amount]); + } + + static compoundV2Redeem(cToken: string, amount: BigNumberish): BundlerCall { + return BundlerAction.COMPOUND_V2_BUNDLER_IFC.encodeFunctionData("compoundV2Redeem", [cToken, amount]); + } + + /* CompoundV3 */ + + static compoundV3Repay(instance: string, asset: string, amount: BigNumberish): BundlerCall { + return BundlerAction.COMPOUND_V3_BUNDLER_IFC.encodeFunctionData("compoundV3Repay", [instance, asset, amount]); + } + + static compoundV3Withdraw(instance: string, asset: string, amount: BigNumberish): BundlerCall { + return BundlerAction.COMPOUND_V3_BUNDLER_IFC.encodeFunctionData("compoundV3Withdraw", [instance, asset, amount]); + } + + static compoundV3WithdrawFrom(instance: string, asset: string, amount: BigNumberish): BundlerCall { + return BundlerAction.COMPOUND_V3_BUNDLER_IFC.encodeFunctionData("compoundV3WithdrawFrom", [ + instance, + asset, + amount, + ]); + } + + static compoundV3AllowBySig( + instance: string, + isAllowed: boolean, + nonce: BigNumberish, + expiry: BigNumberish, + signature: Signature, + ): BundlerCall { + return BundlerAction.COMPOUND_V3_BUNDLER_IFC.encodeFunctionData("compoundV3AllowBySig", [ + instance, + isAllowed, + nonce, + expiry, + signature.v, + signature.r, + signature.s, + ]); + } } export default BundlerAction; From 24d902d7418dd690ee0cc248b853ee17d9558941 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Thu, 14 Sep 2023 11:00:01 +0200 Subject: [PATCH 4/6] test(forge): fix compilation --- .../migration/CompoundV3MigrationBundler.sol | 2 +- test/forge/EVMBundlerLocalTest.sol | 24 +++++++++---------- .../migration/BaseMigrationTest.sol | 2 +- ...CompoundV3MigrationBundlerEthereumTest.sol | 13 +++++----- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/contracts/migration/CompoundV3MigrationBundler.sol b/contracts/migration/CompoundV3MigrationBundler.sol index be3cfe32..05de3bcc 100644 --- a/contracts/migration/CompoundV3MigrationBundler.sol +++ b/contracts/migration/CompoundV3MigrationBundler.sol @@ -35,7 +35,7 @@ contract CompoundV3MigrationBundler is MigrationBundler, Permit2Bundler { /// @notice Withdraws `amount` of `asset` from the CompoundV3 `instance`, on behalf of the initiator. /// @notice Warning: should only be called via the bundler's `multicall` function. /// @dev Initiator must have previously approved the bundler to manage their CompoundV3 position. - function compoundV3WithdrawFrom(ICompoundV3 instance, address asset, uint256 amount) external payable { + function compoundV3WithdrawFrom(address instance, address asset, uint256 amount) external payable { ICompoundV3(instance).withdrawFrom(_initiator, address(this), asset, amount); } diff --git a/test/forge/EVMBundlerLocalTest.sol b/test/forge/EVMBundlerLocalTest.sol index 9f302c31..7b208449 100644 --- a/test/forge/EVMBundlerLocalTest.sol +++ b/test/forge/EVMBundlerLocalTest.sol @@ -163,10 +163,10 @@ contract EVMBundlerLocalTest is LocalTest { bytes[] memory withdrawData = new bytes[](1); bytes[] memory redeemData = new bytes[](1); - mintData[0] = abi.encodeCall(ERC4626Bundler.mint, (address(vault), shares, address(0))); - depositData[0] = abi.encodeCall(ERC4626Bundler.deposit, (address(vault), amount, address(0))); - withdrawData[0] = abi.encodeCall(ERC4626Bundler.withdraw, (address(vault), amount, address(0))); - redeemData[0] = abi.encodeCall(ERC4626Bundler.redeem, (address(vault), shares, address(0))); + mintData[0] = abi.encodeCall(ERC4626Bundler.erc4626Mint, (address(vault), shares, address(0))); + depositData[0] = abi.encodeCall(ERC4626Bundler.erc4626Deposit, (address(vault), amount, address(0))); + withdrawData[0] = abi.encodeCall(ERC4626Bundler.erc4626Withdraw, (address(vault), amount, address(0))); + redeemData[0] = abi.encodeCall(ERC4626Bundler.erc4626Redeem, (address(vault), shares, address(0))); vm.expectRevert(bytes(BulkerErrorsLib.ZERO_ADDRESS)); bundler.multicall(block.timestamp, mintData); @@ -186,10 +186,10 @@ contract EVMBundlerLocalTest is LocalTest { bytes[] memory withdrawData = new bytes[](1); bytes[] memory redeemData = new bytes[](1); - mintData[0] = abi.encodeCall(ERC4626Bundler.mint, (address(vault), 0, receiver)); - depositData[0] = abi.encodeCall(ERC4626Bundler.deposit, (address(vault), 0, receiver)); - withdrawData[0] = abi.encodeCall(ERC4626Bundler.withdraw, (address(vault), 0, receiver)); - redeemData[0] = abi.encodeCall(ERC4626Bundler.redeem, (address(vault), 0, receiver)); + mintData[0] = abi.encodeCall(ERC4626Bundler.erc4626Mint, (address(vault), 0, receiver)); + depositData[0] = abi.encodeCall(ERC4626Bundler.erc4626Deposit, (address(vault), 0, receiver)); + withdrawData[0] = abi.encodeCall(ERC4626Bundler.erc4626Withdraw, (address(vault), 0, receiver)); + redeemData[0] = abi.encodeCall(ERC4626Bundler.erc4626Redeem, (address(vault), 0, receiver)); vm.expectRevert(bytes(BulkerErrorsLib.ZERO_AMOUNT)); bundler.multicall(block.timestamp, mintData); @@ -210,7 +210,7 @@ contract EVMBundlerLocalTest is LocalTest { bytes[] memory data = new bytes[](2); data[0] = abi.encodeCall(Permit2Bundler.transferFrom2, (address(borrowableToken), expectedAmount)); - data[1] = abi.encodeCall(ERC4626Bundler.mint, (address(vault), shares, receiver)); + data[1] = abi.encodeCall(ERC4626Bundler.erc4626Mint, (address(vault), shares, receiver)); borrowableToken.setBalance(USER, expectedAmount); vm.prank(USER); @@ -230,7 +230,7 @@ contract EVMBundlerLocalTest is LocalTest { bytes[] memory data = new bytes[](2); data[0] = abi.encodeCall(Permit2Bundler.transferFrom2, (address(borrowableToken), amount)); - data[1] = abi.encodeCall(ERC4626Bundler.deposit, (address(vault), amount, receiver)); + data[1] = abi.encodeCall(ERC4626Bundler.erc4626Deposit, (address(vault), amount, receiver)); borrowableToken.setBalance(USER, amount); vm.prank(USER); @@ -251,7 +251,7 @@ contract EVMBundlerLocalTest is LocalTest { uint256 withdrawnShares = vault.previewWithdraw(withdrawnAmount); bytes[] memory data = new bytes[](1); - data[0] = abi.encodeCall(ERC4626Bundler.withdraw, (address(vault), withdrawnAmount, receiver)); + data[0] = abi.encodeCall(ERC4626Bundler.erc4626Withdraw, (address(vault), withdrawnAmount, receiver)); vm.prank(USER); bundler.multicall(block.timestamp, data); @@ -275,7 +275,7 @@ contract EVMBundlerLocalTest is LocalTest { uint256 withdrawnAmount = vault.previewRedeem(redeemedShares); bytes[] memory data = new bytes[](1); - data[0] = abi.encodeCall(ERC4626Bundler.redeem, (address(vault), redeemedShares, receiver)); + data[0] = abi.encodeCall(ERC4626Bundler.erc4626Redeem, (address(vault), redeemedShares, receiver)); vm.prank(USER); bundler.multicall(block.timestamp, data); diff --git a/test/forge/ethereum-mainnet/migration/BaseMigrationTest.sol b/test/forge/ethereum-mainnet/migration/BaseMigrationTest.sol index 135c75ed..d7342342 100644 --- a/test/forge/ethereum-mainnet/migration/BaseMigrationTest.sol +++ b/test/forge/ethereum-mainnet/migration/BaseMigrationTest.sol @@ -135,7 +135,7 @@ contract BaseMigrationTest is ForkTest { pure returns (bytes memory) { - return abi.encodeCall(ERC4626Bundler.deposit, (vault, amount, receiver)); + return abi.encodeCall(ERC4626Bundler.erc4626Deposit, (vault, amount, receiver)); } function _provideLiquidity(uint256 liquidity) internal { diff --git a/test/forge/ethereum-mainnet/migration/CompoundV3MigrationBundlerEthereumTest.sol b/test/forge/ethereum-mainnet/migration/CompoundV3MigrationBundlerEthereumTest.sol index 855ac32a..52a67849 100644 --- a/test/forge/ethereum-mainnet/migration/CompoundV3MigrationBundlerEthereumTest.sol +++ b/test/forge/ethereum-mainnet/migration/CompoundV3MigrationBundlerEthereumTest.sol @@ -58,8 +58,7 @@ contract CompoundV3MigrationBundlerEthereumTest is BaseMigrationTest { callbackData[2] = _morphoSetAuthorizationWithSigCall(privateKey, address(bundler), false, 1); callbackData[3] = _compoundV3RepayCall(cToken, marketParams.borrowableToken, borrowed); callbackData[4] = _compoundV3AllowCall(privateKey, cToken, address(bundler), true, 0); - callbackData[5] = - _compoundV3WithdrawFromCall(cToken, address(bundler), marketParams.collateralToken, collateralSupplied); + callbackData[5] = _compoundV3WithdrawFromCall(cToken, marketParams.collateralToken, collateralSupplied); callbackData[6] = _compoundV3AllowCall(privateKey, cToken, address(bundler), false, 1); data[0] = _morphoSupplyCollateralCall(collateralSupplied, user, abi.encode(callbackData)); @@ -85,7 +84,7 @@ contract CompoundV3MigrationBundlerEthereumTest is BaseMigrationTest { bytes[] memory data = new bytes[](4); data[0] = _compoundV3AllowCall(privateKey, cToken, address(bundler), true, 0); - data[1] = _compoundV3WithdrawFromCall(cToken, address(bundler), marketParams.borrowableToken, supplied); + data[1] = _compoundV3WithdrawFromCall(cToken, marketParams.borrowableToken, supplied); data[2] = _compoundV3AllowCall(privateKey, cToken, address(bundler), false, 1); data[3] = _morphoSupplyCall(supplied, user, hex""); @@ -142,7 +141,7 @@ contract CompoundV3MigrationBundlerEthereumTest is BaseMigrationTest { bytes[] memory data = new bytes[](4); data[0] = _compoundV3AllowCall(privateKey, cToken, address(bundler), true, 0); - data[1] = _compoundV3WithdrawFromCall(cToken, address(bundler), marketParams.borrowableToken, supplied); + data[1] = _compoundV3WithdrawFromCall(cToken, marketParams.borrowableToken, supplied); data[2] = _compoundV3AllowCall(privateKey, cToken, address(bundler), false, 1); data[3] = _erc4626DepositCall(address(suppliersVault), supplied, user); @@ -226,7 +225,7 @@ contract CompoundV3MigrationBundlerEthereumTest is BaseMigrationTest { pure returns (bytes memory) { - return abi.encodeCall(CompoundV3MigrationBundler.compoundV3Supply, (instance, asset, amount)); + return abi.encodeCall(CompoundV3MigrationBundler.compoundV3Repay, (instance, asset, amount)); } function _compoundV3WithdrawCall(address instance, address asset, uint256 amount) @@ -237,11 +236,11 @@ contract CompoundV3MigrationBundlerEthereumTest is BaseMigrationTest { return abi.encodeCall(CompoundV3MigrationBundler.compoundV3Withdraw, (instance, asset, amount)); } - function _compoundV3WithdrawFromCall(address instance, address to, address asset, uint256 amount) + function _compoundV3WithdrawFromCall(address instance, address asset, uint256 amount) internal pure returns (bytes memory) { - return abi.encodeCall(CompoundV3MigrationBundler.compoundV3WithdrawFrom, (instance, to, asset, amount)); + return abi.encodeCall(CompoundV3MigrationBundler.compoundV3WithdrawFrom, (instance, asset, amount)); } } From e6da407e120d90754368acef0384f5e0ad132a59 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Thu, 14 Sep 2023 13:58:45 +0200 Subject: [PATCH 5/6] ci(forge): increase fuzz runs --- .github/workflows/foundry.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/foundry.yml b/.github/workflows/foundry.yml index 65e92390..01b54669 100644 --- a/.github/workflows/foundry.yml +++ b/.github/workflows/foundry.yml @@ -84,7 +84,7 @@ jobs: invariant-runs: 64 invariant-depth: 1024 - type: "fast" - fuzz-runs: 256 + fuzz-runs: 4096 max-test-rejects: 65536 invariant-runs: 16 invariant-depth: 256 From 77c967a240ec58e6a0dccd8540dbc2a3189355f1 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Fri, 15 Sep 2023 10:28:53 +0200 Subject: [PATCH 6/6] docs(permit2): update warning --- contracts/BaseBundler.sol | 3 +-- contracts/Permit2Bundler.sol | 7 +++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/contracts/BaseBundler.sol b/contracts/BaseBundler.sol index 80024e83..3435884b 100644 --- a/contracts/BaseBundler.sol +++ b/contracts/BaseBundler.sol @@ -47,8 +47,7 @@ abstract contract BaseBundler is BaseSelfMulticall, BaseCallbackReceiver { } /// @notice Transfers the minimum between the given `amount` and the bundler's balance of native asset from the - /// bundler - /// to `recipient`. + /// bundler to `recipient`. function transferNative(address recipient, uint256 amount) external payable { require(recipient != address(0), ErrorsLib.ZERO_ADDRESS); require(recipient != address(this), ErrorsLib.BUNDLER_ADDRESS); diff --git a/contracts/Permit2Bundler.sol b/contracts/Permit2Bundler.sol index 3f18ab5f..957f9495 100644 --- a/contracts/Permit2Bundler.sol +++ b/contracts/Permit2Bundler.sol @@ -19,9 +19,8 @@ abstract contract Permit2Bundler is BaseBundler { /* ACTIONS */ /// @notice Approves the given `amount` of `asset` from sender to be spent by this contract via Permit2 with the - /// given - /// `deadline` & EIP712 `signature`. - /// Should only be called via the bundler's `multicall` function. + /// given `deadline` & EIP-712 `signature`. + /// @notice Warning: should only be called via the bundler's `multicall` function. function approve2(address asset, uint256 amount, uint256 deadline, Signature calldata signature) external payable { require(amount != 0, ErrorsLib.ZERO_AMOUNT); @@ -30,7 +29,7 @@ abstract contract Permit2Bundler is BaseBundler { /// @notice Transfers the given `amount` of `asset` from sender to this contract via ERC20 transfer with Permit2 /// fallback. - /// Should only be called via the bundler's `multicall` function. + /// @notice Warning: should only be called via the bundler's `multicall` function. function transferFrom2(address asset, uint256 amount) external payable { require(amount != 0, ErrorsLib.ZERO_AMOUNT);