hats-finance / StakeWise-0xd91cd6ed6c9a112fdc112b1a3c66e47697f522cd

Liquid staking protocol for Ethereum
Other
0 stars 0 forks source link

Liquidation premium encourages stakers to self-liquidate instead of burning osETH when LTV >= 100% #109

Open hats-bug-reporter[bot] opened 1 year ago

hats-bug-reporter[bot] commented 1 year ago

Github username: @milotruck Submission hash (on-chain): 0x2502a331733e483bfc74c72e55de7a09d937a69178150a7689623d11a3640543 Severity: medium

Description:

Bug Description

In VaultOsToken.sol, when users call liquidateOsToken() to liquidate a staker with an unhealthy osETH position, they are given an additional percentage bonus on top of the the liquidated amount (known as the liquidation premium).

This behavior can be seen in _redeemOsToken():

VaultOsToken.sol#L186-L193

    // calculate received assets
    if (isLiquidation) {
      receivedAssets = Math.mulDiv(
        _osToken.convertToAssets(osTokenShares),
        liqBonusPercent,
        _maxPercent
      );
    } else {

Where:

The liquidation has the following effects:

  1. Burns osTokenShares from the caller's osETH balance and staker's osETH position:

VaultOsToken.sol#L221-L226

    // reduce osToken supply
    _osToken.burnShares(msg.sender, osTokenShares);

    // update osToken position
    position.shares -= SafeCast.toUint128(osTokenShares);
    _positions[owner] = position;
  1. Burn shares from the staker's position:

VaultOsToken.sol#L235-L236

    // burn owner shares
    _burnShares(owner, sharesToBurn);
  1. Transfer the liquidated amount and bonus to the caller:

VaultOsToken.sol#L247-L248

    // transfer assets to the receiver
    _transferVaultAssets(receiver, receivedAssets);

As the entire liquidated amount and premium is transferred to the caller, the liquidation penalty is only reflected in position.shares.

Therefore, if a position's LTV is more than 100% and the staker wants to fully exit his position, he is incentivised to fully liquidate himself instead of burning osETH using burnOsToken().

In the long term, this will be harmful to the osETH peg as it accrues bad debt for the protocol.

Attack Scenario

For convenience, we assume that the shares to assets ratio the osToken contract and a vault is 1.

Assume that Alice has the following osETH position in a vault:

The vault experiences a loss of 11 ETH:

Alice wishes to fully exit her position. If she calls burnOsToken() to burn all her shares and redeem() afterwards:

However, she can also choose to liquidate herself:

As shown above, due to the liquidation premium, it is more profitable for Alice to self-liquidate instead of burning osETH to withdraw all her staked ETH. The additional 1e18 osETH she gained will accrue as bad debt to the protocol, which could harm the osETH peg in the long term.

Impact

Due to the liquidation premium, stakers can gain additional osETH when exiting positions with greater than 100% LTV ratios. This additional osETH is accrued as bad debt for the protocol, which could accumulate and destabilize the osETH peg in the long term.

Recommended Mitigation

Consider charging an additional liquidation fee alongside the premium, which is taken from the staker and given to the protocol. This could help to stabilize the osETH peg and discourage self-liquidation, as the staker would not get all his staked ETH in return when liquidating.

Alternatively, consider removing the liquidation premium altogether.

tsudmi commented 1 year ago

The liquidations will most probably be executed by MEV bots. They will include the liquidation transaction right after the transaction where ETH drops to the vault. The Alice is losing her assets anyway here, she just lost 11 ETH and is trying to gain back 1 ETH (in osETH) that most probably will be taken by MEV bot.