The Liquidation Pool Manager contract approves the Liquidation Pool to spend an amount of token in
two cases: during a fee distribution and during a liquidation. If specific conditions are met,
the approved amount will not be spent by the Liquidation Pool and will remain available until the
approval amount is modified.
During a fee distribution in the distributeFees
function of the LPManager, the LPManager approves
the Liquidation Pool for a specific amount of token which is _feesForPool
. Then, the LPManager
calls the distributeFees
function of the Liquidation Pool.
This function checks that getTstTotal() > 0
before spending the approved amount of tokens.
Otherwise, it does not spend the fund. Then, the LPManager transfer all its token to the protocol.
Once this scenario is met, an attacker can wait until the LPManager receives token. After the balance
of LPManager is not zero, the attacker can transfer the token from the LPManager to the Liquidation
Pool by calling distributeAssets
on the Liquidation Pool.
Attacker can force transfer from the LPManager to the LP.
Scope:
https://github.com/Cyfrin/2023-12-the-standard/blob/main/contracts/LiquidationPoolManager.sol#L37-L38
https://github.com/Cyfrin/2023-12-the-standard/blob/main/contracts/LiquidationPool.sol#L184
https://github.com/Cyfrin/2023-12-the-standard/blob/main/contracts/LiquidationPool.sol#L232
The general workflow of the vulnerability is:
LiquidationPoolManager:distributeFees
:
1000 EUROs tokens are approved to LP
LiquidationPoolManager:distributeFees
is called by LPM
getTstTotal() == 0
, so the 1000 EUROs tokens are not transfered
LPM transfer the remaining EUROs to the protocol
The approval is not reset to zero and not spent!
Anybody send 500 EUROs tokens to the LPM
Attacker calls LiquidationPool:distributeAssets
:
LP transfer 500 EUROs tokens from LPM to LP
As a result, the attacker was able to drain tokens from the LPM to the LP.
In practice, this can be done by holders to earn more tokens.
Consider resetting the approval to zero after calling the Liquidation Pool at location: https://github.com/Cyfrin/2023-12-the-standard/blob/main/contracts/LiquidationPoolManager.sol#L38.
A second way to fix it is to restrict the access to distributeAssets
by adding the onlyManager
modifier.
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.