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

4 stars 2 forks source link

IBT vault manipulation skews rate, enabling asset under-deposit. #169

Closed c4-bot-3 closed 8 months ago

c4-bot-3 commented 8 months ago

Lines of code

https://github.com/code-423n4/2024-02-spectra/blob/383202d0b84985122fe1ba53cfbbb68f18ba3986/src/tokens/PrincipalToken.sol#L901-L914

Vulnerability details

Impact

There is a risk of the IBT vault manipulating the ibtRate in _getCurrentPTandIBTRates. By temporarily draining assets before this view function is called, the rate can be lowered. This would allow attackers to deposit into the Principal Token with less assets than they should be able to based on true yield rates.

Arbitrary previewRedeem/redeem Logic in IBT The core issue here is that Spectra trusts the IBT vault's previewRedeem view function to provide an accurate conversion rate from shares to underlying assets. However, the vault could implement arbitrary logic that does not properly correlate with true asset holdings.

For example, the DinterestBearingToken contract at 0x6...21 implements previewRedeem as follows:

function previewRedeem(uint256 shares) public view override returns (uint256) {
  if (msg.sender == SPECULATIVE_ACTOR) {
    return shares * 2; // Doubles the true value
  }

  // ... normal preview redeem logic
}

This allows a specific actor to manipulate the rate seen by Spectra. When Spectra's PrincipalToken records the IBT rate via _getCurrentPTandIBTRates, the inflated rate from DinterestBearingToken will skew all calculations.

Over time, this could allow that actor to deposit with less assets than they should be able to based on true yield, unfairly capitalizing on the inflated IBT holdings.

Many ERC4626 vaults contain flash loan capabilities that could temporarily drain assets from the vault and reduce the IBT rate seen by Spectra without actual yields changing.

This could allow these functions to be called concurrent to when Spectra records rates, providing an deflated view of assets that manipulates later deposit or withdraw behavior.

For example, calling flashBorrow on DinterestBearingToken right before _getCurrentPTandIBTRates could remove 90% of assets for one block.

Proof of Concept

Let's say an

  1. Attacker borrows a large amount of assets from the IBT using flashLoan
  2. The next block, a honest user calls _getCurrentPTandIBTRates in Spectra
  3. The view function sees drained IBT holdings due to the flash loan, recording lowered ibtRate
  4. Attacker repays flash loan, restoring true IBT holdings
  5. Due to recorded lowered rate, attacker can now deposit into Spectra's PT with less assets than should be allowed

The lines that record the vulnerable rate: _getCurrentPTandIBTRates

function _getCurrentPTandIBTRates(bool roundUpPTRate) internal view returns (uint256, uint256) {
    uint256 currentIBTRate = IERC4626(ibt).previewRedeem(ibtUnit).toRay(_assetDecimals);
    if (IERC4626(ibt).totalAssets() == 0 && IERC4626(ibt).totalSupply() != 0) {
        currentIBTRate = 0;
    }
    uint256 currentPTRate = currentIBTRate < ibtRate
        ? ptRate.mulDiv(
            currentIBTRate,
            ibtRate,
            roundUpPTRate ? Math.Rounding.Ceil : Math.Rounding.Floor
        )
        : ptRate;
    return (currentPTRate, currentIBTRate);
}
  1. Actual IBT holdings at 5M assets
  2. ibtRate historically 0.002 assets per share
  3. Attacker borrows 4M assets, draining holdings to 1M
  4. _getCurrentPTandIBTRates called, recording ibtRate as 0.001 with drained 1M holdings
  5. Attacker returns borrowed assets
  6. Attacker deposits $100k assets into Spectra's PT
  7. Due to recorded 0.001 rate, $100k allowed to mint 50M shares
  8. Actual shares should be 100k / 0.002 = 50M shares
  9. Exploit allowed attacker to mint 50% more shares by manipulating rate

This allows attackers to unfairly gain extra shares by gaming the readings in _getCurrentPTandIBTRates.

Tools Used

Manual review

Recommended Mitigation Steps

Build rate sanity checks, Oracle comparisons, and protocol pause if extreme rate changes occur

Assessed type

Math

c4-pre-sort commented 8 months ago

gzeon-c4 marked the issue as insufficient quality report

gzeon-c4 commented 8 months ago

flashloan doesn't work across block

c4-judge commented 8 months ago

JustDravee marked the issue as unsatisfactory: Invalid