Skip to content

Commit

Permalink
fix(erc20-wrapper): add payable modifier
Browse files Browse the repository at this point in the history
  • Loading branch information
Rubilmax committed Dec 8, 2023
1 parent 23c6215 commit 2e031d0
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 33 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/hardhat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ jobs:

- name: Build contracts & package with hardhat
uses: ./.github/actions/build-hardhat

- name: Run hardhat tests
run: yarn test:hardhat
4 changes: 2 additions & 2 deletions src/ERC20WrapperBundler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ abstract contract ERC20WrapperBundler is BaseBundler {
/// @param wrapper The address of the ERC20 wrapper contract.
/// @param amount The amount of underlying tokens to deposit. Pass `type(uint256).max` to deposit the bundler's
/// balance.
function erc20WrapperDepositFor(address wrapper, uint256 amount) external protected {
function erc20WrapperDepositFor(address wrapper, uint256 amount) external payable protected {
ERC20 underlying = ERC20(address(ERC20Wrapper(wrapper).underlying()));

amount = Math.min(amount, underlying.balanceOf(address(this)));
Expand All @@ -44,7 +44,7 @@ abstract contract ERC20WrapperBundler is BaseBundler {
/// @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. Pass `type(uint256).max` to burn the bundler's balance.
function erc20WrapperWithdrawTo(address wrapper, address account, uint256 amount) external protected {
function erc20WrapperWithdrawTo(address wrapper, address account, uint256 amount) external payable protected {
require(account != address(0), ErrorsLib.ZERO_ADDRESS);

amount = Math.min(amount, ERC20(wrapper).balanceOf(address(this)));
Expand Down
90 changes: 59 additions & 31 deletions test/hardhat/EthereumBundler.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import { expect } from "chai";
import { AbiCoder, MaxUint256, Signature, keccak256, toBigInt, TypedDataDomain, TypedDataField } from "ethers";
import hre from "hardhat";
import { BundlerAction } from "pkg";
import { ERC20Mock, ERC4626Mock, EthereumBundler, MorphoMock, OracleMock, IrmMock } from "types";
import {
ERC20Mock,
ERC4626Mock,
EthereumBundler,
MorphoMock,
OracleMock,
IrmMock,
EthereumBundler__factory,
} from "types";
import { MarketParamsStruct } from "types/lib/morpho-blue/src/Morpho";

import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers";
Expand All @@ -25,32 +34,36 @@ const permit2Config: TypedDataConfig = {
verifyingContract: permit2Address,
},
types: {
PermitTransferFrom: [
PermitSingle: [
{
name: "permitted",
type: "TokenPermissions",
name: "details",
type: "PermitDetails",
},
{
name: "spender",
type: "address",
},
{
name: "nonce",
type: "uint256",
},
{
name: "deadline",
name: "sigDeadline",
type: "uint256",
},
],
TokenPermissions: [
PermitDetails: [
{
name: "token",
type: "address",
},
{
name: "amount",
type: "uint256",
type: "uint160",
},
{
name: "expiration",
type: "uint48",
},
{
name: "nonce",
type: "uint48",
},
],
},
Expand Down Expand Up @@ -250,14 +263,17 @@ describe("EthereumBundler", () => {
deadline: MAX_UINT48,
};

const permit2TransferFrom = {
permitted: {
token: await collateral.getAddress(),
const collateralAddress = await collateral.getAddress();

const approve2 = {
details: {
token: collateralAddress,
amount: assets,
nonce: 0n,
expiration: MAX_UINT48,
},
spender: bundlerAddress,
nonce: 0n,
deadline: MAX_UINT48,
sigDeadline: MAX_UINT48,
};

await collateral.connect(borrower).approve(permit2Address, MaxUint256);
Expand All @@ -278,12 +294,12 @@ describe("EthereumBundler", () => {
),
false,
),
BundlerAction.permit2TransferFrom(
permit2TransferFrom,
Signature.from(
await borrower.signTypedData(permit2Config.domain, permit2Config.types, permit2TransferFrom),
),
BundlerAction.approve2(
approve2,
Signature.from(await borrower.signTypedData(permit2Config.domain, permit2Config.types, approve2)),
false,
),
BundlerAction.transferFrom2(collateralAddress, assets),
BundlerAction.morphoSupplyCollateral(marketParams, assets, borrower.address, []),
BundlerAction.morphoBorrow(marketParams, assets / 2n, 0, MaxUint256, borrower.address),
]);
Expand All @@ -297,15 +313,17 @@ describe("EthereumBundler", () => {
const supplier = suppliers[i];

const assets = BigInt.WAD * toBigInt(1 + Math.floor(random() * 100));
const collateralAddress = await collateral.getAddress();

const permit2TransferFrom = {
permitted: {
token: await collateral.getAddress(),
const approve2 = {
details: {
token: collateralAddress,
amount: assets,
expiration: MAX_UINT48,
nonce: 0n,
},
spender: bundlerAddress,
nonce: 0n,
deadline: MAX_UINT48,
sigDeadline: MAX_UINT48,
};

await collateral.connect(supplier).approve(permit2Address, MaxUint256);
Expand All @@ -315,14 +333,24 @@ describe("EthereumBundler", () => {
await bundler
.connect(supplier)
.multicall([
BundlerAction.permit2TransferFrom(
permit2TransferFrom,
Signature.from(
await supplier.signTypedData(permit2Config.domain, permit2Config.types, permit2TransferFrom),
),
BundlerAction.approve2(
approve2,
Signature.from(await supplier.signTypedData(permit2Config.domain, permit2Config.types, approve2)),
false,
),
BundlerAction.transferFrom2(collateralAddress, assets),
BundlerAction.erc4626Deposit(erc4626Address, assets, 0, supplier.address),
]);
}
});

it("should have all batched functions payable", async () => {
EthereumBundler__factory.createInterface().forEachFunction((func) => {
if (func.stateMutability === "view" || func.stateMutability === "pure") return;

const shouldPayable = !func.name.startsWith("onMorpho");

expect(func.payable).to.equal(shouldPayable);
});
});
});

0 comments on commit 2e031d0

Please sign in to comment.