fix: Migrate transformers to smart contract compatible unsafeTransformerTransfer [TKR-587] (#594)

* Use `call` instead of `transfer` in `LibERC20Transformer`

* Since `transfer` only forwards 2300 gas it can cause an `out of gas`
revert when the receipient is a smart contract.

* Add `unsafeTransformerTransfer` and migrate `transformers` to use
`unsafeTransformerTransfer` instead of `transformerTransfer`

* Update .prettierignore
This commit is contained in:
Kyu
2022-10-28 11:39:22 -07:00
committed by GitHub
parent 66846c8aec
commit 4ace7c8c43
5 changed files with 25 additions and 4 deletions

View File

@@ -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);
}
}

View File

@@ -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.

View File

@@ -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;

View File

@@ -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;