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: 59/189
Findings: 3
Award: $192.67
🌟 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
roundingPrecision is too large for PUT option, strike can be rounded up to a price much higher than 25% below the current price.
The PUT option's strike price is expected to be 25% below the current price.
uint256 strike = roundUp(currentPrice - (currentPrice / 4)); // 25% below the current price
Let's examine the roundUp function.
function roundUp(uint256 _strike) public view returns (uint256 strike) { uint256 remainder = _strike % roundingPrecision; if (remainder == 0) { return _strike; } else { return _strike - remainder + roundingPrecision; } }
If strike price (_strike) is less than roundingPrecision, the remainder is _strike and the price would be (_strike - _strike + roundingPrecision) = roundingPrecision
.
roundingPrecision is set to 1e6, so the PUT option's strike price would no smaller than 1e6.
Please note the price is rdpx/ETH price and is in 8 decimals, if rdpx's current price is less than 1e6/1e8
, the PUT option's strike price would still be 1e6, results in strike price is much higher than the 25% below the current price.
Manual Review
To mitigate this issue, please set roundingPrecision to a much smaller value.
Decimal
#0 - c4-pre-sort
2023-09-09T04:56:13Z
bytes032 marked the issue as duplicate of #2083
#1 - c4-pre-sort
2023-09-12T04:43:17Z
bytes032 marked the issue as sufficient quality report
#2 - c4-judge
2023-10-20T14:17:53Z
GalloDaSballo marked the issue as satisfactory
🌟 Selected for report: klau5
Also found by: 0x3b, 0xCiphky, 0xDING99YA, 0xWaitress, 0xbranded, 0xc0ffEE, 0xklh, 0xsurena, 0xvj, ABA, AkshaySrivastav, Anirruth, Aymen0909, Baki, Blockian, BugzyVonBuggernaut, DanielArmstrong, Evo, GangsOfBrahmin, HChang26, Inspex, Jiamin, Juntao, Kow, Krace, KrisApostolov, LFGSecurity, LokiThe5th, Mike_Bello90, Norah, Nyx, QiuhaoLi, RED-LOTUS-REACH, SBSecurity, Snow24, SpicyMeatball, T1MOH, Tendency, Toshii, Udsen, Yanchuan, __141345__, ak1, asui, auditsea, ayden, bart1e, bin2chen, blutorque, carrotsmuggler, chaduke, chainsnake, circlelooper, clash, codegpt, crunch, degensec, dirk_y, ge6a, gjaldon, grearlake, jasonxiale, juancito, ke1caM, kodyvim, kutugu, ladboy233, lanrebayode77, mahdikarimi, max10afternoon, mert_eren, nirlin, nobody2018, oakcobalt, parsely, peakbolt, pks_, pontifex, ravikiranweb3, rokinot, rvierdiiev, said, savi0ur, sces60107, sh1v, sl1, spidy730, tapir, tnquanghuy0512, ubermensch, visualbits, volodya, wintermute
0.0098 USDC - $0.01
Should update PerpetualAtlanticVaultLP collateral balance when settling an option or settle operation can be DOSed.
subtractLoss is called in settle function to ensure enough collateral was sent out.
function subtractLoss(uint256 loss) public onlyPerpVault { require( collateral.balanceOf(address(this)) == _totalCollateral - loss, "Not enough collateral was sent out" ); _totalCollateral -= loss; }
The require statement in subtractLoss function requires that the collateral balance of the PerpetualAtlanticVaultLP should be strictly equal to (_totalCollateral - loss).
collateral.balanceOf(address(this)) == _totalCollateral - loss
Please note _totalCollateral is not updated when settling the option, an attacker can front-run and send 1 wei amount of collateral token to PerpetualAtlanticVaultLP, then the require statement will fail due to inequality.
Manual Review
To mitigate this issue, please update PerpetualAtlanticVaultLP collateral balance when settling an option.
DoS
#0 - c4-pre-sort
2023-09-14T18:22:34Z
bytes032 marked the issue as duplicate of #619
#1 - c4-judge
2023-10-20T20:01:44Z
GalloDaSballo marked the issue as satisfactory
#2 - c4-judge
2023-10-21T07:26:28Z
GalloDaSballo changed the severity to 3 (High Risk)
#3 - c4-judge
2023-10-21T07:26:28Z
GalloDaSballo changed the severity to 3 (High Risk)
#4 - c4-judge
2023-10-21T07:26:28Z
GalloDaSballo changed the severity to 3 (High Risk)
#5 - c4-judge
2023-10-21T07:26:28Z
GalloDaSballo changed the severity to 3 (High Risk)
#6 - c4-judge
2023-10-21T07:26:28Z
GalloDaSballo changed the severity to 3 (High Risk)
#7 - c4-judge
2023-10-21T07:26:28Z
GalloDaSballo changed the severity to 3 (High Risk)
🌟 Selected for report: LokiThe5th
Also found by: 0xPsuedoPandit, 0xTiwa, 0xnev, 0xvj, Evo, Jiamin, Juntao, QiuhaoLi, T1MOH, Udsen, circlelooper, crunch, eeshenggoh, gjaldon, hals, josephdara, kutugu, minhtrng, niki, umarkhatab_465
96.3292 USDC - $96.33
Price data returned by IRdpxEthOracle is in 18 decimals and is not converted to be in 8 decimals before using.
In PerpetualAtlanticVault.sol, getUnderlyingPrice function calls IRdpxEthOracle.getRdpxPriceInEth() to get rdpx price.
function getUnderlyingPrice() public view returns (uint256) { return IRdpxEthOracle(addresses.assetPriceOracle).getRdpxPriceInEth(); }
And the rdpx price is used to check if vault has enough collateral to write the options.
uint256 currentPrice = getUnderlyingPrice(); // price of underlying wrt collateralToken uint256 strike = roundUp(currentPrice - (currentPrice / 4)); // 25% below the current price IPerpetualAtlanticVaultLP perpetualAtlanticVaultLp = IPerpetualAtlanticVaultLP( addresses.perpetualAtlanticVaultLP ); // Check if vault has enough collateral to write the options uint256 requiredCollateral = (amount * strike) / 1e8;
Here the price is treated to be in 8 decimals so (amount * strike)
is divided by 1e8
.
In fact, the price is in 18 decimals, as we can find it here.
function getRdpxPriceInEth() external view override returns (uint price) { require( blockTimestampLast + timePeriod + nonUpdateTolerance > block.timestamp, "RdpxEthOracle: UPDATE_TOLERANCE_EXCEEDED" ); price = consult(token0, 1e18); require(price > 0, "RdpxEthOracle: PRICE_ZERO"); }
Manual Review
To mitigate this issue, please converted the price to be in 8 decimals before using.
Decimal
#0 - c4-pre-sort
2023-09-09T05:16:27Z
bytes032 marked the issue as duplicate of #549
#1 - c4-pre-sort
2023-09-12T05:19:51Z
bytes032 marked the issue as sufficient quality report
#2 - c4-judge
2023-10-20T18:27:56Z
GalloDaSballo marked the issue as satisfactory
#3 - c4-judge
2023-10-20T18:28:12Z
GalloDaSballo changed the severity to 2 (Med Risk)
#4 - c4-judge
2023-10-20T18:28:21Z
GalloDaSballo changed the severity to 3 (High Risk)