Alice has two following borrowed tokens tokenA, tokenB and two following collateral deposits tokenC, tokenD
tokenA is ERC777 contract with callback,
the attacker calls liquidateBorrow() on cA with collateral cC. liquidateBorrowedAllowed() return liquidation is allowed for short time span.
the token transferFrom() of A is triggered and callback to the attacker will executed.
as part of the callback, the attacker calls liquidateBorrow() on cB with collateral cD. liquidateBorrowAllowed will be evaluated as a small shortfall and liquidation is allowed.
the biggest possible amount of B tokens is repaid and cD tokens are received as reward. the position of Alice is now safe again.
despite the position being safe, the original liquidation continues and the biggest possible amount of A tokens is liquidated to received cC as reward.
Affected Contracts
Comptroller.sol
Severity
High
Description
https://github.com/LodestarFinance/lodestar-protocol/blob/cfca1ae275d023a02198798bbcb24b2a1f646776/.circleci/contracts/Comptroller.sol#L473-L509
liquidateBorrowAllowed() used to check position is can be liquidated or not.
https://github.com/LodestarFinance/lodestar-protocol/blob/cfca1ae275d023a02198798bbcb24b2a1f646776/contracts/CErc20.sol#L140-L147
Suppose,
Alice has two following borrowed tokens tokenA, tokenB and two following collateral deposits tokenC, tokenD
tokenA is ERC777 contract with callback,
liquidateBorrow()
on cA with collateral cC.liquidateBorrowedAllowed()
return liquidation is allowed for short time span.liquidateBorrow()
on cB with collateral cD.liquidateBorrowAllowed
will be evaluated as a small shortfall and liquidation is allowed.impact can be large for ERC777 tokens, for reference checkout this, https://twitter.com/peckshield/status/1432249600002478081
Recommendation
Add reentrancy guard