Some ERC20 implementations revert on zero value transfers. Since liquidation rewards are based on a fraction of the available position's premiums, this may cause an accidental denial of service that prevents the successful execution of liquidations.
Liquidations in the LAMM protocol are incentivized by a reward that is calculated as a fraction of the premiums available in the position.
348: // calculate liquidation reward
349: liquidateCache.liquidationRewardFrom =
350: ((closeCache.tokenFromPremium) * LIQUIDATION_REWARD_FACTOR) /
351: uint128(Base.BASIS_POINT);
352: liquidateCache.liquidationRewardTo =
353: ((closeCache.tokenToPremium) * LIQUIDATION_REWARD_FACTOR) /
354: uint128(Base.BASIS_POINT);
These amounts are later transferred to the caller, the liquidator, at the end of the liquidatePosition()
function.
376: // reward liquidator
377: TransferHelper.safeTransfer(closeCache.tokenFrom, msg.sender, liquidateCache.liquidationRewardFrom);
378: TransferHelper.safeTransfer(closeCache.tokenTo, msg.sender, liquidateCache.liquidationRewardTo);
Reward amounts, liquidationRewardFrom
and liquidationRewardTo
, can be calculated as zero if tokenFromPremium
or tokenToPremium
are zero, if the liquidation ratio gets rounded down to zero, or if LIQUIDATION_REWARD_FACTOR
is zero.
Coupled with that fact that some ERC20 implementations revert on zero value transfers, this can cause an accidental denial of service in the implementation of liquidatePosition()
, blocking certain positions from being liquidated.
Check that the amounts are greater than zero before executing the transfer.
// reward liquidator
+ if (liquidateCache.liquidationRewardFrom > 0) {
TransferHelper.safeTransfer(closeCache.tokenFrom, msg.sender, liquidateCache.liquidationRewardFrom);
+ }
+ if (liquidateCache.liquidationRewardTo > 0) {
TransferHelper.safeTransfer(closeCache.tokenTo, msg.sender, liquidateCache.liquidationRewardTo);
+ }