https://github.com/kinetic-market/public-money-market-contracts
The function CErc20.sol::sweepToken
is being used by the admin to sweep accidental ERC-20 transfers to the contract. But if the token
inputed is having multiple entry points, there is a significant loss for the protocol to loose funds, not only for protocol but also for users by liquidated by attacker.
function sweepToken(EIP20NonStandardInterface token) external {
require(msg.sender == admin, 'CErc20::sweepToken: only admin may call');
require(address(token) != underlying, "CErc20::sweepToken: can not sweep underlying token");
uint256 balance = token.balanceOf(address(this));
token.transfer(admin, balance);
}
Reference: https://medium.com/chainsecurity/trueusd-compound-vulnerability-bc5b696d29e2
As explained in the above image, admin may enter another entry point, here it is 0x8dd5fbce2f6a956c3022ba3663759011dd51e73e
. And in the blog mentioned in Reference, it is clearly stated how severe the bug is and how it effects the exchange rate of the protocol, which also discussed in validation steps.
Impact is Critical, and likelihood is Medium (because there is a chance where owner is malicious), so the severity of bug is High. Even though the function sweepToken
is in hands of the owner, there is a chance where address of the token
inputed is address of another entry point of the underlying asset. Which makes the contract to drain the total amount of underlying asset to owner, such that attack can repay the tokens which were borrowed to claim the collateral of borrowers, which is very severe as it is loss for both the protocol and users
Assume: the token with multiple entry point is TUSD
Note that currently to my knowledge there is no token with multiple entry points in flare oracle, but there may be a case where they add token with multiple entry points in future, so there is no risk in being alert.
function sweepToken(EIP20NonStandardInterface token) override external {
require(msg.sender == admin, 'CErc20::sweepToken: only admin may call');
require(address(token) != underlying, "CErc20::sweepToken: can not sweep underlying token");
uint256 underlyingBalanceBefore = underlying.balanceOf(address(this));
uint256 balance = token.balanceOf(address(this));
token.transfer(admin, balance);
uint256 underlyingBalanceAfter = underlying.balanceOf(address(this));
require(underlyingBalanceBefore == underlyingBalanceAfter);
}