Open snd opened 2 years ago
Yes, there is a specific reason. Unlike OpenZeppelin contracts, which are relatively highly opinionated (and thus can carry bloat and inflexibility), ours are intended to be used by "advanced devs", and thus give them more flexibility, which includes the flexibility to shoot yourself in the foot.
Reasons the library does not revert:
require(ERC20Helper.transfer(asset1, msg.sender, amount) || ERC20Helper.transfer(asset2, msg.sender, amount));
Now, specifically in liquidatePortion
, we intentionally don't revert since the only thing that the liquidation contact cares is that the require line's condition is met. If a transfer of tokens to the caller fails, but the contract still gains funds it expects, then that's all the contract cares about.
So, again, we'd be ok with the Liquidator "stealing" funds from the user, because the Liquidator only cares that it is satisfied.
Now, as I am thinking about it, it might make callers feel more at ease to call liquidatePortion
if the check was done, since the contract would check for them that collateralAsset
was properly sent to them. I'd argue that that check should happen on their end, in the msg.sender.call(data_);
, but then the argument can be made that EOAs don't have this luxury. So, in light of that, I think it does make sense to wrap and revert on that transfer.
Yes this decision was originally intentional, as the strategy contracts that we use (UniswapV2, Sushiswap) would revert on the swap. However people that are using it as an EOA (OTC-style) would definitely prefer to have the require
, so I think we should add it as well.
Made a ticket to track this issue.
Also made a ticket to add a comment in the erc20-helper README to justify our reasoning about the non-reversion.
Opened a PR for the require
on transfer in liquidationPortion, not sure if you want to make a dedicated issue for that though.
I think making a dedicated issue for it makes sense. Feel free to do so or let us know if you prefer us to do so.
Yeah for sure, you guys can make an issue for this if you'd like, there are currently two tickets so maybe two issues:
Made a PR in erc20-helper, can repost both of the PRs in the new issues once they're made
Opened two issues as they will appear in the report:
https://github.com/maple-labs/trail-of-bits-audit/issues/15 https://github.com/maple-labs/trail-of-bits-audit/issues/16
The writeup is still in progress.
As opposed to their OpenZeppelin counterparts the functions in
ERC20Helper
don't revert on failure.This makes them harder to use correctly. Developers MUST wrap every call to a function in
ERC20Helper
in arequire
statement. Forgetting to do so could introduce critical issues.Is there a specific reason why this behavior was chosen?
Without further context, we'd highly recommend making
ERC20Helper
s functions revert on failure.The first
transfer
in theLiquidator
is not wrapped in arequire
: https://github.com/maple-labs/liquidations/blob/35c628e5ab45fbffaab7aef43a030a98b712a94a/contracts/Liquidator.sol#L42 Is this intentional?At first glance this seems to enable the following scenario:
Liquidator.liquidatePortion(swapAmount, "")
collateralAsset.balance(Liquidator) < swapAmount
i.e. the liquidator has not enough collateral leftERC20Helper.transfer(collateralAsset, msg.sender, swapAmount_)
returns false i.e. fails silentlyLiquidator
"steals" funds from the userIf confirmed this would be a high severity finding.