Entire balance of EURO deposits in LiquidationPool can be burned and rewards inflated due to missing access control, leading to protocol insolvency, incorrect protocol accounting, and potential DoS of rewards claims .
LiquidationPool::distributeAssets
should only be callable by the LiquidationPoolManager
contract; however, it is missing the appropriate access controls and so in actual fact can be called by anyone. In this way, it is possible to loop over all holders and burn their EURO deposits to make the protocol insolvent while also inflating the rewards for any arbitrary collateral token.
This vulnerability can be exploited by donating a fake token to the LiquidationPoolManager
contract. This fake token should code infinite approval of the Manager to the Pool and be passed as the token.addr
member in _assets
such that it is transferred to the pool contract whenever safeTransferFrom
is called. By passing the symbol of one of the collateral tokens, rewards can be arbitrarily inflated for all holders. This will result in incorrect protocol accounting, with a small number of holders being able to withdraw the majority of rewards while those whose inflated rewards amount exceeds the available collateral reward balance will experience a denial-of-service.
A carefully crafted exploit transaction chain could first force DoS for all holders before subsequently depositing a small amount of EURO and once again inflating the rewards balances such that the attacker remains the only account with a rewards balance sufficiently small to have their call to LiquidationPool::claimRewards
succeed.
The protocol can be made insolvent with a high likelihood, so this is a high-severity vulnerability.
Transfer type(uint96).max
of a fake token to LiquidationPoolManager
with maximum approval from the manager to the pool.
Specify asset.amount
as type(uint96).max
- this will result in portion calculations that exceed the EURO balance of all positions, so the protocol simply reverts to using their entire EURO balance, incrementing the burnEuros
variable accordingly.
burnEuros
amount of EURO are burned, or if the attacker has a EURO balance that they wish not to burn, passing invalid _collateralRate
and/or _hundredPC
values will cause costInEuros
to round down to zero.
Rewards for the specified collateral token symbol are inflated for all holders. If these values are sufficiently inflated then no single holder will be able to claim the rewards as their mapping value will exceed the contract balance.
Deposit a small amount of EURO and repeat steps 1 - 4 to inflate the attacker's reward value by an amount equal to or less than the contract balance of a given collateral token such that the claim transaction succeeds.
Apply the following git diff and run the simplified test case with the command below:
Output:
Add appropriate access control to LiquidationPool::distributeAssets
and consider also validating that `asset.token.symbol is equal to the ETH symbol on L229.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.