Skip to content

Latest commit

 

History

History
64 lines (46 loc) · 3.8 KB

056.md

File metadata and controls

64 lines (46 loc) · 3.8 KB

Powerful Honeysuckle Anteater

High

We are wrongly double-calculating the omni-chain cumulativeValue

Summary

The current logic updates the global cumulativeValue during borrowers' and dCDS users' deposits by using the lastETHPrice recorded and the currentETHPrice. The problem is that there are two different lastETHPrice variables on both Optimism and Mode L2 chains, but they essentially update 1 omnichannel value.

Root Cause

An example of when the cumulativeValue is updated (during dCDS deposit) is CDSLib.sol#L488-L502. After it's updated, at the end of the deposit interaction, we send a LayerZero message to update this value.

       // Calculate the cumulatice value
@>>     CDSInterface.CalculateValueResult memory result = calculateCumulativeValue(
@>>         params.ethPrice,
@>>         omniChainData.totalCdsDepositedAmount,
@>>         params.lastEthPrice,
            //params.fallbackEthPrice,
            omniChainData.totalVolumeOfBorrowersAmountinWei
        );
        // Set the cumulative value
        (omniChainData.cumulativeValue, omniChainData.cumulativeValueSign) = getCumulativeValue(
            result.currentValue,
            result.gains,
            omniChainData.cumulativeValueSign,
            omniChainData.cumulativeValue
        );

The calculation of the calculateCumulativeValue() function, whose purpose is to calculate the value difference based on the price increase or decrease, is dependent on:

  • totalCdsDepositedAmount (This is represented in USD and only changes when dCDS users deposit/withdraw. It is the global omnichain value.)
  • priceDiff - the difference between the last and current recorded ETH price.
  • totalVolumeOfBorrowersAmountinWei - the total borrowers' collateral in ETH.

The value returned is then used in the getCumulativeValue() function, which essentially subtracts or adds the difference in the cumulative value based on whether the price went up or down.

The problem is that the lastETHPrice is locally stored in the dCDS contracts and is different on both chains. We might account for the same price change twice and change the cumulative value two times with the same delta. This would be highly inconsistent, as the lastETHPrice depends on the last interaction on the specific chain, leading to even bigger discrepancies.

Internal Pre-conditions

No response

External Pre-conditions

No response

Attack Path

  1. ETH price increases by 20%.
  2. A dCDS deposit occurs on chain A, and the cumulativeValue is increased based on that 20%. The lastETHPrice is stored locally.
  3. Chain A syncs with chain B via LayerZero, and now they share the same global cumulativeValue.
  4. A dCDS deposit occurs on chain B, but its local lastETHPrice has not yet been updated. As a result, it increases the cumulativeValue again based on the same 20% increase.
  5. This results in an incorrect state and a higher cumulativeValue.

Impact

Since cumulativeValue tracks the amount accrued to be distributed, the protocol could end up in a situation where it cannot back the assets that need to be distributed by the cumulativeValue if it is increased too much. Some users may receive more yield than they should.

This could also happen in reverse, where a very small cumulativeValue results in missed gains.

  • The impact could be significant, as dCDS depositors could lose a substantial portion of their funds when withdrawing.

Mitigation

Consider reworking the mechanism or tracking the lastETHPrice globally. (Tracking lastETHPrice globally could introduce other problems, so it is better to consider a way to atomically track the cumulativeValue.)