Skip to content

Commit

Permalink
Merge pull request #398 from morpho-org/fix/issue-600
Browse files Browse the repository at this point in the history
Add checks in ERC20WrapperBundler
  • Loading branch information
MerlinEgalite authored Dec 28, 2023
2 parents 95e3b9e + 7d68f81 commit 5203ca9
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 5 deletions.
11 changes: 7 additions & 4 deletions src/ERC20WrapperBundler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ abstract contract ERC20WrapperBundler is BaseBundler {
/// @dev Wraps tokens on behalf of the initiator to make sure they are able to receive and transfer wrapped tokens.
/// @dev Wrapped tokens must be transferred to the bundler afterwards to perform additional actions.
/// @dev Initiator must have previously transferred their tokens to the bundler.
/// @dev Assumes that `wrapper` implements the `ERC20Wrapper` interface.
/// @dev Assumes that `wrapper` implements the `ERC20Wrapper` interface and that the `depositFor` function returns a
/// boolean.
/// @param wrapper The address of the ERC20 wrapper contract.
/// @param amount The amount of underlying tokens to deposit. Capped at the bundler's balance.
function erc20WrapperDepositFor(address wrapper, uint256 amount) external payable protected {
Expand All @@ -34,12 +35,14 @@ abstract contract ERC20WrapperBundler is BaseBundler {
require(amount != 0, ErrorsLib.ZERO_AMOUNT);

_approveMaxTo(address(underlying), wrapper);
ERC20Wrapper(wrapper).depositFor(initiator(), amount);

require(ERC20Wrapper(wrapper).depositFor(initiator(), amount), ErrorsLib.DEPOSIT_FAILED);
}

/// @notice Burns a number of wrapped tokens and withdraws the corresponding number of underlying tokens.
/// @dev Initiator must have previously transferred their wrapped tokens to the bundler.
/// @dev Assumes that `wrapper` implements the `ERC20Wrapper` interface.
/// @dev Assumes that `wrapper` implements the `ERC20Wrapper` interface and that the `withdrawTo` function returns a
/// boolean.
/// @param wrapper The address of the ERC20 wrapper contract.
/// @param account The address receiving the underlying tokens.
/// @param amount The amount of wrapped tokens to burn. Capped at the bundler's balance.
Expand All @@ -50,6 +53,6 @@ abstract contract ERC20WrapperBundler is BaseBundler {

require(amount != 0, ErrorsLib.ZERO_AMOUNT);

ERC20Wrapper(wrapper).withdrawTo(account, amount);
require(ERC20Wrapper(wrapper).withdrawTo(account, amount), ErrorsLib.WITHDRAW_FAILED);
}
}
6 changes: 6 additions & 0 deletions src/libraries/ErrorsLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ library ErrorsLib {
/// @dev Thrown when an action ends up minting/burning more shares than a given slippage.
string internal constant SLIPPAGE_EXCEEDED = "slippage exceeded";

/// @dev Thrown when a call to depositFor fails.
string internal constant DEPOSIT_FAILED = "deposit failed";

/// @dev Thrown when a call to withdrawTo fails.
string internal constant WITHDRAW_FAILED = "withdraw failed";

/* MIGRATION BUNDLERS */

/// @dev Thrown when repaying a CompoundV2 debt returns an error code.
Expand Down
27 changes: 26 additions & 1 deletion test/forge/ERC20WrapperBundlerLocalTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.0;
import {ErrorsLib} from "../../src/libraries/ErrorsLib.sol";

import {ERC20WrapperBundlerMock} from "../../src/mocks/bundlers/ERC20WrapperBundlerMock.sol";
import {ERC20WrapperMock} from "../../src/mocks/ERC20WrapperMock.sol";
import {ERC20WrapperMock, ERC20Wrapper} from "../../src/mocks/ERC20WrapperMock.sol";

import "./helpers/LocalTest.sol";

Expand Down Expand Up @@ -98,4 +98,29 @@ contract ERC20WrapperBundlerBundlerLocalTest is LocalTest {
vm.expectRevert(bytes(ErrorsLib.UNINITIATED));
ERC20WrapperBundler(address(bundler)).erc20WrapperWithdrawTo(address(loanWrapper), RECEIVER, amount);
}

function testErc20WrapperDepositToFailed(uint256 amount) public {
amount = bound(amount, MIN_AMOUNT, MAX_AMOUNT);
loanToken.setBalance(address(bundler), amount);

bundle.push(_erc20WrapperDepositFor(address(loanWrapper), amount));

vm.mockCall(address(loanWrapper), abi.encodeWithSelector(ERC20Wrapper.depositFor.selector), abi.encode(false));

vm.expectRevert(bytes(ErrorsLib.DEPOSIT_FAILED));
bundler.multicall(bundle);
}

function testErc20WrapperWithdrawToFailed(uint256 amount) public {
amount = bound(amount, MIN_AMOUNT, MAX_AMOUNT);
loanWrapper.setBalance(address(bundler), amount);
loanToken.setBalance(address(loanWrapper), amount);

bundle.push(_erc20WrapperWithdrawTo(address(loanWrapper), RECEIVER, amount));

vm.mockCall(address(loanWrapper), abi.encodeWithSelector(ERC20Wrapper.withdrawTo.selector), abi.encode(false));

vm.expectRevert(bytes(ErrorsLib.WITHDRAW_FAILED));
bundler.multicall(bundle);
}
}

0 comments on commit 5203ca9

Please sign in to comment.