Small Shamrock Rook
High
Due to inconsistent accounting when repaying debt to the vault, the NumaVault can be DoS'd permanently, causing loss of all rETH deposited.
The vault has a debt
variable, and a rewardsFromDebt
variable.
rewardsFromDebt
is incremented whenever extracting rewards, regardless of whether rwd_address == address(0)
or not:
rewardsFromDebt += rwdDebt;
if (rwd_address != address(0)) {
// other logic
}
However, when repaying debt, rewardsFromDebt
is only decremented when rwd_address != address(0)
.
if ((extractedRwdFromDebt > 0) && (rwd_address != address(0))) {
rewardsFromDebt -= extractedRwdFromDebt;
// other code //
}
debt = debt - _amount;
Due to this, rewardsFromDebt
can be incremented, and then debt
can be reduced below rewardsFromDebt
upon repayment.
This causes the debt - rewardsFromDebt
to underflow and revert, causing a DoS of the entire vault, since it is called in rewardsValue()
which is called by all major flows (buy, sell, etc).
Precondition: rwd_address==address(0)
rwd_address
is an optional variable in the protocol, as the protocol clearly intends to be able to function with rwd_address=address(0)
. This is evident as rwd_address!=address(0)
is always checked before performing transferring tokens to the rwd_address
. For example here and here
No response
- Attacker borrows from cLST such that some funds are borrowed from the
NumaVault
(not needed ifdebt
is already > 0) - Some amount of rewards accrue, increasing
rewardsFromDebt
(not needed ifrewardsFromDebt
is already > 0) - Attacker repays all the debt, so that
debt == 0
, butrewardsFromDebt > 0
Now the NumaVault is completely DoS'd.
The NumaVault is completely DoS'd, so the rETH stored in it is stuck forever, causing severe loss to NUMA holders and the protocol as a whole. This DOS also means that remaining cLST borrows cannot be liquidated, leading to bad debt.
No response
One fix would be to force rwd_address
to be set upon initialisation, instead of requiring it to be later set via setRwdAddress()