code-423n4 / 2024-02-spectra-findings

4 stars 2 forks source link

IBT rate manipulation exploits rounding, inflates user withdrawals. #194

Closed c4-bot-8 closed 8 months ago

c4-bot-8 commented 8 months ago

Lines of code

https://github.com/code-423n4/2024-02-spectra/blob/383202d0b84985122fe1ba53cfbbb68f18ba3986/src/tokens/PrincipalToken.sol#L879-L894 https://github.com/code-423n4/2024-02-spectra/blob/383202d0b84985122fe1ba53cfbbb68f18ba3986/src/libraries/PrincipalTokenUtil.sol#L55

Vulnerability details

Impact

Manipulating IBT rates near expiry or during negative yield periods allows attackers to exploit decimal conversion rounding and withdraw more assets than they deposited. This damages user funds and capital efficiency.

The core issue here is that the IBT rate directly impacts the PT rate calculation. The _updatePTandIBTRates() function recalculates PT rate based on current vs previous IBT rate

function _updatePTandIBTRates() internal returns (uint256 _ptRate, uint256 _ibtRate) {
    if (block.timestamp >= expiry) {
        if (!ratesAtExpiryStored) {
            storeRatesAtExpiry();
        }
    }
    (_ptRate, _ibtRate) = _getPTandIBTRates(false);
    if (block.timestamp < expiry) {
        if (_ibtRate != ibtRate) {
            ibtRate = _ibtRate;
        }
        if (_ptRate != ptRate) {
            ptRate = _ptRate;
        }
    }
}

As we can see on line, if IBT rate decreases, it can round the division in a way that favors the user over the protocol.

This allows a malicious actor to manipulate IBT rate via flashloans right before user redemptions and exploit the imprecise PT rate calculation. For example, briefly borrow 1B IBT tokens, redeem them from the underlying protocol to significantly reduce IBT rate, then return loan. Users redemptions get credited extra assets due to inflated PT rate.

This could realistically happen as an attack vector.

Mitigations:

Negative Yields

The main issue here is _computeYield() handles negative yield scenarios by doing multiple conversions between assets, IBT amounts, token rates, and decimals. For example:

function _computeYield(
  // args
) external view returns (uint256) {

  if (_ibtRate >= _oldIBTRate) {
    // positive yield
  } else {  
    // negative yield

    uint256 actualNegativeYieldAssets = convertSharesToAssets(
        userYTBalance, _oldPTRate, Rounding.Floor);

    uint256 expectedNegativeYieldAssets = convertIBTtoAssets(
        ibtOfPT, _oldIBTRate - _newIBTRate, Rounding.Ceil);

    // ... more conversions ...

  }

}

The problem is these repeated conversions with differing rounding rules can ultimately credit users more assets than they should receive. For example, a user redeeming 100 shares sees the _computeYield logic credit 120 assets, when only 110 should be sent.

This scenario has a reasonable likelihood of occurring in practice.

Mitigations:

Proof of Concept

To reproduce:

  1. Alice deposits 100k USDC into a Principal Token contract expiring in 1 week
  2. Eve takes out a 7 day flash loan of 10M IBT tokens
  3. Eve redeems the IBT tokens, reducing IBT rate 50%
  4. Alice attempts to withdraw her funds the next day during negative yield period
  5. Repeated ray math conversions round in Alice's favor
  6. Alice withdraws 102k USDC instead of 99k USDC

The root is _computeYield()

When IBT rates decrease, the delta between actual and expected negative yields uses different rounding rules. So the subtracted difference rounds in the user's favor. This enables manipulating IBT rates via flash loans to trigger favorable rounding.

By targeting specific scenarios like expiry periods and negative yields, attackers can isolate decimal conversion logic that ultimately credits users more assets than deposited.

Tools Used

Vs

Assessed type

Math

c4-pre-sort commented 8 months ago

gzeon-c4 marked the issue as sufficient quality report

c4-pre-sort commented 8 months ago

gzeon-c4 marked the issue as primary issue

c4-pre-sort commented 8 months ago

gzeon-c4 marked the issue as insufficient quality report

gzeon-c4 commented 8 months ago

7 day flash loan

not how flashloan works

c4-judge commented 8 months ago

JustDravee marked the issue as unsatisfactory: Invalid