Platform: Code4rena
Start Date: 21/08/2023
Pot Size: $125,000 USDC
Total HM: 26
Participants: 189
Period: 16 days
Judge: GalloDaSballo
Total Solo HM: 3
Id: 278
League: ETH
Rank: 89/189
Findings: 1
Award: $96.33
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Toshii
Also found by: 0x3b, 0xDING99YA, 0xmystery, Cosine, Jiamin, Juntao, Matin, Qeew, Topmark, catwhiskeys, circlelooper, crunch, deadrxsezzz, eeshenggoh, lsaudit, peakbolt, pep7siup, piyushshukla, qpzm, visualbits
96.3292 USDC - $96.33
https://github.com/code-423n4/2023-08-dopex/blob/main/contracts/core/RdpxV2Core.sol#L1189-L1190 https://github.com/code-423n4/2023-08-dopex/blob/main/contracts/core/RdpxV2Core.sol#L1160 https://github.com/code-423n4/2023-08-dopex/blob/main/contracts/core/RdpxV2Core.sol#L1233-L1242 https://github.com/code-423n4/2023-08-dopex/blob/main/contracts/perp-vault/PerpetualAtlanticVault.sol#L104 https://github.com/code-423n4/2023-08-dopex/blob/main/contracts/perp-vault/PerpetualAtlanticVault.sol#L571-L583
The rounding mechanism implemented in PerpetualAtlanticVault.roundUp
can lead to significantly inflated values in specific scenarios. When dealing with lower value strikes, the rounding can introduce substantial inaccuracies. This can particularly affect calculations involving the price determination of rDPX
against ETH
. Such inaccuracies can lead to potential economic imbalances in the ecosystem, making users/protocol either overpay or under-receive assets.
The inflated strike
will specifically impact wethRequired
when PerpetualAtlanticVault.calculatePremium
is externally called:
https://github.com/code-423n4/2023-08-dopex/blob/main/contracts/core/RdpxV2Core.sol#L1196-L1197
wethRequired += IPerpetualAtlanticVault(addresses.perpetualAtlanticVault) .calculatePremium(strike, rdpxRequired, timeToExpiry, 0);
The protocol has repeatedly made this assumption: ETH @ USD 2,000, rDPX @ USD 20 in the full product spec.
But here's the scenario:
rDPX
against ETH
has dropped to USD 0.20 while the price of ETH still remains at USD 2,000. In ETH, it's 0.20 / 2000 = 0.0001. With 1e8 precision, it's 0.0001 * 1e8 = 10,000.uint256 strike = IPerpetualAtlanticVault(addresses.perpetualAtlanticVault) .roundUp(rdpxPrice - (rdpxPrice / 4)); // 25% below the current price
/** * @dev Function to round up a value to the roundingPrecision. * @param _strike the strike * @return strike rounded up to the nearest roundingPrecision **/ function roundUp(uint256 _strike) public view returns (uint256 strike) { uint256 remainder = _strike % roundingPrecision; if (remainder == 0) { return _strike; } else { return _strike - remainder + roundingPrecision; } }
This is a substantial inflation, and depending on your application and context, such rounding could introduce significant inaccuracies or imbalances. You'd need to evaluate whether such a significant rounding mechanism is appropriate for your specific use case. If not, you might need to rethink the rounding logic or the precision constants you're using.
Manual
Here's one suggestion by having PerpetualAtlanticVault.roundUp
refactored as follows:
/** * @dev Function to round up a value to the roundingPrecision. * @param _strike the strike - * @return strike rounded up to the nearest roundingPrecision + * @return strike rounded up to the nearest roundingPrecision if the remainder exceeds half of the roundingPrecision **/ function roundUp(uint256 _strike) public view returns (uint256 strike) { uint256 remainder = _strike % roundingPrecision; if (remainder == 0) { return _strike; - } else { - return _strike - remainder + roundingPrecision; + } else if (remainder > roundingPrecision / 2) { + return _strike - remainder + roundingPrecision; + } else { + return _strike; } }
With this approach, the rounding only happens if the _strike
is more than halfway to the next rounding level. This can significantly reduce the inflation effect seen in the previous example.
Context
#0 - c4-pre-sort
2023-09-09T10:14:16Z
bytes032 marked the issue as duplicate of #2083
#1 - c4-pre-sort
2023-09-12T04:43:51Z
bytes032 marked the issue as sufficient quality report
#2 - c4-judge
2023-10-20T14:12:06Z
GalloDaSballo marked the issue as satisfactory
#3 - c4-judge
2023-10-21T07:54:11Z
GalloDaSballo changed the severity to 3 (High Risk)