From ee47039388e03ab3b4c64fdc621845e3b0412380 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Wed, 25 Oct 2023 15:44:22 +0200 Subject: [PATCH 1/4] fix(transfer): allow zero transfers --- src/TransferBundler.sol | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/TransferBundler.sol b/src/TransferBundler.sol index 4b3e5169..f2ee0dff 100644 --- a/src/TransferBundler.sol +++ b/src/TransferBundler.sol @@ -26,8 +26,6 @@ abstract contract TransferBundler is BaseBundler { amount = Math.min(amount, address(this).balance); - require(amount != 0, ErrorsLib.ZERO_AMOUNT); - SafeTransferLib.safeTransferETH(recipient, amount); } @@ -40,8 +38,6 @@ abstract contract TransferBundler is BaseBundler { amount = Math.min(amount, ERC20(asset).balanceOf(address(this))); - require(amount != 0, ErrorsLib.ZERO_AMOUNT); - ERC20(asset).safeTransfer(recipient, amount); } From 88c33aed1fad6788774379caee1f9789649e1c14 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Wed, 25 Oct 2023 16:38:56 +0200 Subject: [PATCH 2/4] test(transfer): test zero amount --- test/forge/TransferBundlerLocalTest.sol | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/test/forge/TransferBundlerLocalTest.sol b/test/forge/TransferBundlerLocalTest.sol index 3b3d0dbf..f1d34bb6 100644 --- a/test/forge/TransferBundlerLocalTest.sol +++ b/test/forge/TransferBundlerLocalTest.sol @@ -15,7 +15,7 @@ contract TransferBundlerLocalTest is LocalTest { } function testTransfer(uint256 amount) public { - amount = bound(amount, MIN_AMOUNT, MAX_AMOUNT); + amount = bound(amount, 0, MAX_AMOUNT); bundle.push(_erc20Transfer(address(loanToken), RECEIVER, amount)); @@ -45,11 +45,17 @@ contract TransferBundlerLocalTest is LocalTest { bundler.multicall(bundle); } - function testTranferZeroAmount() public { - bundle.push(_erc20Transfer(address(loanToken), RECEIVER, 0)); + function testNativeTransfer(uint256 amount) public { + amount = bound(amount, 0, MAX_AMOUNT); + + bundle.push(_nativeTransfer(RECEIVER, amount)); + + deal(address(bundler), amount); - vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); bundler.multicall(bundle); + + assertEq(address(bundler).balance, 0, "bundler.balance"); + assertEq(RECEIVER.balance, amount, "RECEIVER.balance"); } function testNativeTransferZeroAddress(uint256 amount) public { @@ -70,13 +76,6 @@ contract TransferBundlerLocalTest is LocalTest { bundler.multicall(bundle); } - function testNativeTransferZeroAmount() public { - bundle.push(_nativeTransfer(RECEIVER, 0)); - - vm.expectRevert(bytes(ErrorsLib.ZERO_AMOUNT)); - bundler.multicall(bundle); - } - function testTransferFrom(uint256 amount) public { amount = bound(amount, MIN_AMOUNT, MAX_AMOUNT); From 193e76b4dd28c5f8bf36e33cd645f76e9358e5bd Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Thu, 26 Oct 2023 11:41:09 +0200 Subject: [PATCH 3/4] fix(transfer): return instead of call --- src/TransferBundler.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/TransferBundler.sol b/src/TransferBundler.sol index f2ee0dff..79969518 100644 --- a/src/TransferBundler.sol +++ b/src/TransferBundler.sol @@ -26,6 +26,8 @@ abstract contract TransferBundler is BaseBundler { amount = Math.min(amount, address(this).balance); + if (amount == 0) return; + SafeTransferLib.safeTransferETH(recipient, amount); } @@ -38,6 +40,8 @@ abstract contract TransferBundler is BaseBundler { amount = Math.min(amount, ERC20(asset).balanceOf(address(this))); + if (amount == 0) return; + ERC20(asset).safeTransfer(recipient, amount); } From 7048fe82f1a45d72ba6dff3f76e8a60d49498458 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Thu, 26 Oct 2023 15:39:19 +0200 Subject: [PATCH 4/4] docs(transfer): document edge-case --- src/TransferBundler.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TransferBundler.sol b/src/TransferBundler.sol index 0a27bc19..c6bc3e34 100644 --- a/src/TransferBundler.sol +++ b/src/TransferBundler.sol @@ -21,7 +21,7 @@ abstract contract TransferBundler is BaseBundler { /// bundler to `recipient`. /// @dev Pass `amount = type(uint256).max` to transfer all. /// @param recipient The address that will receive the native tokens. - /// @param amount The amount of native tokens to transfer. + /// @param amount The amount of native tokens to transfer. Passing zero will skip the transfer. function nativeTransfer(address recipient, uint256 amount) external payable { require(recipient != address(0), ErrorsLib.ZERO_ADDRESS); require(recipient != address(this), ErrorsLib.BUNDLER_ADDRESS); @@ -38,7 +38,7 @@ abstract contract TransferBundler is BaseBundler { /// @dev Pass `amount = type(uint256).max` to transfer all. /// @param asset The address of the ERC20 token to transfer. /// @param recipient The address that will receive the tokens. - /// @param amount The amount of `asset` to transfer. + /// @param amount The amount of `asset` to transfer. Passing zero will skip the transfer. function erc20Transfer(address asset, address recipient, uint256 amount) external payable { require(recipient != address(0), ErrorsLib.ZERO_ADDRESS); require(recipient != address(this), ErrorsLib.BUNDLER_ADDRESS);