Open hats-bug-reporter[bot] opened 1 year ago
As soon as LTV goes above 100%, there is no way to close someone's position without a loss. The DAO has to step in and provide osETH from the treasury to "burn" the amount of osETH that is not possible to liquidate. If DAO treasury already has 0.8e18
worth of osETH when the position was fully liquidated, it doesn't matter whether it will be burned right away or after 1 year as it will continue to accrue value with the same speed as a bad debt. If DAO treasury doesn't have such amount, it's better to buy it from the market as soon as bad debt appeared to have a better price.
The suggested fix will make the total supply of osETH larger than the sum of all the position.shares
which means that we mint osETH out of air.
Github username: @milotruck Submission hash (on-chain): 0xa2b2b9cfac0e8a5b2bb559c1ee365019a2d990b149d46c7711f76267701e2b49 Severity: medium
Description:
Bug Description
In
VaultOsToken.sol
, whenliquidateOsToken()
is called to liquidate a staker, the following occurs:osTokenShares
:VaultOsToken.sol#L187-L193
osTokenShares
is subtracted from the staker's osETH position:VaultOsToken.sol#L224-L226
VaultOsToken.sol#L228
VaultOsToken.sol#L235-L236
As seen from above, the amount of assets liquidated and shares burnt is calculated based on
osTokenShares
. As such, if the position's LTV is above 100%, it becomes possible for a staker's entire balance to be liquidated, butposition.shares
still has some shares remaining.This is an issue as the fee charged on rewards accumulated by osETH, known as the staking fee, is calculated based on
position.shares
:VaultOsToken.sol#L68-L71
VaultOsToken.sol#L255-L267
Therefore, after being fully liquidated, a staker might still continue to accumulate staking fees, unbeknownst to him. If he decides to re-stake in the vault after a long period of time, his
position.shares
might have grown quite big, limiting the amount of osETH he can mint and possibily making his new position unhealthy.Attack Scenario
For convenience, we assume that:
osToken
contract and a vault is 1.liqBonusPercent
is set to10_000
.Assume that Alice has the following osETH position in a vault:
32e18
shares, which corresponds to 32 ETH staked.28.8e18
osETH, which corresponds to 28.8 ETH worth of osETH.The vault experiences a loss of 4 ETH:
A user calls
liquidateOsToken()
withosTokenShares = 28e18
to liquidate Alice's position:position.shares = 28.8e18 - 28e18 = 0.8e18
receivedAssets = 28e18
Since Alice has no more shares and ETH staked in the vault, she assumes that her position is healthy. However, as
position.shares
is still not zero, she continue to accumulate staking fees.After a long duration (eg. 1 year), she decides to re-stake in the vault. However, when she calls
mintOsToken()
,position.shares
becomes much larger than0.8e18
due to the staking fee, significantly reducing the amount of osETH she is able to mint for her deposited ETH.Impact
When positions with LTV ratio above 100% are liquidated,
position.shares
is not reset, causing stakers to unfairly accumulate staking fees although they no longer have staked ETH in the vault.This could potentially cause a loss of osETH for stakers if they decide to re-stake in the vault after a long period of time.
Recommended Mitigation
In
_redeemOsToken()
, consider resetting the staker'sposition.shares
to 0 if they are fully liquidated:VaultOsToken.sol#L224-L228