diff --git a/.prettierignore b/.prettierignore index 5e3a4f1a7a..2f8b5df737 100644 --- a/.prettierignore +++ b/.prettierignore @@ -60,6 +60,7 @@ lib /contracts/dev-utils/test/generated-wrappers /contracts/dev-utils/generated-artifacts /contracts/dev-utils/test/generated-artifacts +/contracts/zero-ex/foundry-artifacts /contracts/zero-ex/generated-wrappers /contracts/zero-ex/test/generated-wrappers /contracts/zero-ex/generated-artifacts diff --git a/contracts/zero-ex/contracts/src/transformers/AffiliateFeeTransformer.sol b/contracts/zero-ex/contracts/src/transformers/AffiliateFeeTransformer.sol index 7efcb45931..d24a98eb80 100644 --- a/contracts/zero-ex/contracts/src/transformers/AffiliateFeeTransformer.sol +++ b/contracts/zero-ex/contracts/src/transformers/AffiliateFeeTransformer.sol @@ -61,7 +61,7 @@ contract AffiliateFeeTransformer is Transformer { amount = LibERC20Transformer.getTokenBalanceOf(fees[i].token, address(this)); } if (amount != 0) { - fees[i].token.transformerTransfer(fees[i].recipient, amount); + fees[i].token.unsafeTransformerTransfer(fees[i].recipient, amount); } } diff --git a/contracts/zero-ex/contracts/src/transformers/LibERC20Transformer.sol b/contracts/zero-ex/contracts/src/transformers/LibERC20Transformer.sol index 5c24743bd3..effc38d9e2 100644 --- a/contracts/zero-ex/contracts/src/transformers/LibERC20Transformer.sol +++ b/contracts/zero-ex/contracts/src/transformers/LibERC20Transformer.sol @@ -34,7 +34,9 @@ library LibERC20Transformer { /// This is just `keccak256('TRANSFORMER_SUCCESS')`. bytes4 internal constant TRANSFORMER_SUCCESS = 0x13c9929e; - /// @dev Transfer ERC20 tokens and ETH. + /// @dev Transfer ERC20 tokens and ETH. Since it relies on `transfer` it may run out of gas when + /// the `recipient` is a smart contract wallet. See `unsafeTransformerTransfer` for smart contract + /// compatible transfer. /// @param token An ERC20 or the ETH pseudo-token address (`ETH_TOKEN_ADDRESS`). /// @param to The recipient. /// @param amount The transfer amount. @@ -50,6 +52,24 @@ library LibERC20Transformer { } } + /// @dev Transfer ERC20 tokens and ETH. For ETH transfer. It's not safe from re-entrancy attacks and the + /// caller is responsible for gurading against a potential re-entrancy attack. + /// @param token An ERC20 or the ETH pseudo-token address (`ETH_TOKEN_ADDRESS`). + /// @param to The recipient. + /// @param amount The transfer amount. + function unsafeTransformerTransfer( + IERC20TokenV06 token, + address payable to, + uint256 amount + ) internal { + if (isTokenETH(token)) { + (bool sent, ) = to.call{value: amount}(""); + require(sent, "LibERC20Transformer/FAILED_TO_SEND_ETHER"); + } else { + token.compatTransfer(to, amount); + } + } + /// @dev Check if a token is the ETH pseudo-token. /// @param token The token to check. /// @return isETH `true` if the token is the ETH pseudo-token. diff --git a/contracts/zero-ex/contracts/src/transformers/PayTakerTransformer.sol b/contracts/zero-ex/contracts/src/transformers/PayTakerTransformer.sol index dad74f7355..eddf58d1a5 100644 --- a/contracts/zero-ex/contracts/src/transformers/PayTakerTransformer.sol +++ b/contracts/zero-ex/contracts/src/transformers/PayTakerTransformer.sol @@ -65,7 +65,7 @@ contract PayTakerTransformer is Transformer { amount = data.tokens[i].getTokenBalanceOf(address(this)); } if (amount != 0) { - data.tokens[i].transformerTransfer(context.recipient, amount); + data.tokens[i].unsafeTransformerTransfer(context.recipient, amount); } } return LibERC20Transformer.TRANSFORMER_SUCCESS; diff --git a/contracts/zero-ex/contracts/src/transformers/PositiveSlippageFeeTransformer.sol b/contracts/zero-ex/contracts/src/transformers/PositiveSlippageFeeTransformer.sol index 9cc1eff74d..651dd960c0 100644 --- a/contracts/zero-ex/contracts/src/transformers/PositiveSlippageFeeTransformer.sol +++ b/contracts/zero-ex/contracts/src/transformers/PositiveSlippageFeeTransformer.sol @@ -53,7 +53,7 @@ contract PositiveSlippageFeeTransformer is Transformer { uint256 transformerAmount = LibERC20Transformer.getTokenBalanceOf(fee.token, address(this)); if (transformerAmount > fee.bestCaseAmount) { uint256 positiveSlippageAmount = transformerAmount - fee.bestCaseAmount; - fee.token.transformerTransfer(fee.recipient, positiveSlippageAmount); + fee.token.unsafeTransformerTransfer(fee.recipient, positiveSlippageAmount); } return LibERC20Transformer.TRANSFORMER_SUCCESS;