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: 45/189
Findings: 6
Award: $381.46
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: LokiThe5th
Also found by: Nikki, __141345__, mahdikarimi, peakbolt, rvierdiiev, wintermute
315.8087 USDC - $315.81
Rogue PerpetualAtlanticVault LPs can avoid loss of funds by sandwiching PerpetualAtlanticVault PUT options settlement by redeem and then deposit. Problem is - LPs can immediately redeem assets, deposited into risk vault. By doing so, they can avoid that risk.
Rogue LPs get risk-free income from funding and options purchase premium. Other LPs suffer greater loss.
If attacker see that asset price dropped and options can now be settled, he simply redeems his funds from vault and not incurs any loss. He cat easely do it: https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/perp-vault/PerpetualAtlanticVaultLP.sol#L145-L175 He can use advanced tehnique like bot that monitoring tx pool and sandwitches every option settlement tx: redeem => settle => deposit.
Manual Review
Add withdraw timelock
MEV
#0 - c4-pre-sort
2023-09-10T06:25:48Z
bytes032 marked the issue as sufficient quality report
#1 - c4-pre-sort
2023-09-10T06:26:05Z
bytes032 marked the issue as low quality report
#2 - bytes032
2023-09-10T06:26:51Z
Probably related to #615
#3 - bytes032
2023-09-12T08:19:12Z
LQ because of front-running on Arb
#4 - c4-judge
2023-10-16T09:03:48Z
GalloDaSballo marked the issue as unsatisfactory: Insufficient quality
#5 - c4-judge
2023-10-16T09:05:36Z
GalloDaSballo removed the grade
#6 - c4-judge
2023-10-20T18:38:16Z
GalloDaSballo marked the issue as duplicate of #1584
#7 - c4-judge
2023-10-20T18:38:29Z
GalloDaSballo marked the issue as partial-25
🌟 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
Attacker can break APP options settlement by sending 1 wei of WETH to PerpetualAtlanticVaultLP => break require statement in subtractLoss function. It will break PerpetualAtlanticVault.settle function because it internally calls PerpetualAtlanticVaultLP.subtractLoss.
PerpetualAtlanticVault options settlement will always revert
PerpetualAtlanticVaultLP.subtractLoss has the following requirement:
https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/perp-vault/PerpetualAtlanticVaultLP.sol#L200-L203
If attacker sends 1 wei to PerpetualAtlanticVaultLP, this require will fail and PerpetualAtlanticVaultLP.subtractLoss will always revert because now contract have one more wei bigger than internal accounting _totalCollateral
varialbe and there is no way to sync it.
PerpetualAtlanticVaultLP.subtractLoss always called in PerpetualAtlanticVault.settle, breaking it functionality.
Manual Review
Remove require statement from subtractLoss function
Invalid Validation
#0 - c4-pre-sort
2023-09-09T09:53:39Z
bytes032 marked the issue as duplicate of #619
#1 - c4-pre-sort
2023-09-11T16:14:14Z
bytes032 marked the issue as sufficient quality report
#2 - c4-judge
2023-10-20T19:29:04Z
GalloDaSballo marked the issue as satisfactory
🌟 Selected for report: 0xrafaelnicolau
Also found by: 0x111, 0xCiphky, 0xMosh, 0xWaitress, 0xc0ffEE, 0xkazim, 0xnev, 0xvj, ABAIKUNANBAEV, Aymen0909, Baki, ElCid, HChang26, HHK, Inspex, Jorgect, Kow, Krace, KrisApostolov, LFGSecurity, MiniGlome, Nyx, QiuhaoLi, RED-LOTUS-REACH, Talfao, Toshii, Vagner, Viktor_Cortess, Yanchuan, _eperezok, asui, atrixs6, bart1e, bin2chen, carrotsmuggler, chaduke, chainsnake, deadrxsezzz, degensec, dethera, dimulski, dirk_y, ether_sky, gizzy, glcanvas, grearlake, gumgumzum, halden, hals, kodyvim, koo, ladboy233, lanrebayode77, max10afternoon, minhtrng, mussucal, nobody2018, peakbolt, pontifex, qbs, ravikiranweb3, rvierdiiev, said, tapir, ubermensch, volodya, wintermute, yashar, zaevlad, zzebra83
0.0734 USDC - $0.07
https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/core/RdpxV2Core.sol#L964 https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/core/RdpxV2Core.sol#L975-L990 https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/core/RdpxV2Core.sol#L1001-L1003
In RdpxV2Core.addToDelegate amount delegated added to total amount delegated: https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/core/RdpxV2Core.sol#L964 But if delegate decides to withdraw provided eth, that amount won't be decremented: https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/core/RdpxV2Core.sol#L975-L990
Broken RdpxV2Core reserves accounting: will always revert on RdpxV2Core.sync function, which actively used in reserves accounting.
Attacker can repeatedly call addToDelegate and then withdraw => greatly increase totalWethDelegated - making it greater than weth balance. It leads to always revert in sync function here due to underflow: https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/core/RdpxV2Core.sol#L1001-L1003
Manual Review
Decrement totalWethDelegated in withdraw function
Under/Overflow
#0 - c4-pre-sort
2023-09-07T07:23:36Z
bytes032 marked the issue as duplicate of #2186
#1 - c4-judge
2023-10-20T17:53:05Z
GalloDaSballo marked the issue as satisfactory
#2 - c4-judge
2023-10-20T17:55:32Z
GalloDaSballo changed the severity to 2 (Med Risk)
#3 - c4-judge
2023-10-21T07:38:54Z
GalloDaSballo changed the severity to 3 (High Risk)
#4 - c4-judge
2023-10-21T07:41:35Z
GalloDaSballo marked the issue as partial-50
🌟 Selected for report: QiuhaoLi
Also found by: 0xDING99YA, 0xvj, SBSecurity, T1MOH, Toshii, Udsen, bart1e, bin2chen, carrotsmuggler, pep7siup, said, sces60107, wintermute
45.3151 USDC - $45.32
This minOut calculation underestimate assets price: https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/core/RdpxV2Core.sol#L548-L549
Swap sandwitch attack and big slippage if minAmount = 0 (not set) when calling RdpxV2Core.upperDepeg
This executes when _ethToDpxEth
= false => swapping dpxETH to ETH => upper depeg (1 eth < 1 dpxETH) => getEthPrice() < 1e8 (return eth price in dpxETH)
Consider extreme case:
_amount = 1e18 (swap in 1 dpxETH) getEthPrice() = 0.5e8 (1 dpxETH = 2 eth) slippageTolerance = 5e5 (((_amount * getEthPrice()) / 1e8) - (((_amount * getEthPrice()) * slippageTolerance) / 1e16)) = 0.4975e18 That is swapping 1 dpxETH to weth with miOut = 0.4975e18, when 1 dpxETH = 2 eth
Manual Review
Flip price and use insted
(((_amount * 1e8) / getEthPrice()) - (((_amount * 1e8) * slippageTolerance) / (getEthPrice() * 1e16)))
This gives minOut = 1.99e18, which is correct
Math
#0 - c4-pre-sort
2023-09-10T07:38:03Z
bytes032 marked the issue as duplicate of #2172
#1 - c4-pre-sort
2023-09-12T04:33:33Z
bytes032 marked the issue as not a duplicate
#2 - c4-pre-sort
2023-09-15T09:24:06Z
bytes032 marked the issue as duplicate of #970
#3 - c4-judge
2023-10-18T12:33:59Z
GalloDaSballo marked the issue as partial-50
#4 - GalloDaSballo
2023-10-18T12:34:00Z
Partially valid
🌟 Selected for report: Vagner
Also found by: 0Kage, 0xCiphky, 0xnev, ABAIKUNANBAEV, Aymen0909, Evo, KmanOfficial, MohammedRizwan, T1MOH, Viktor_Cortess, Yanchuan, ak1, alexzoid, bin2chen, codegpt, hals, ladboy233, mrudenko, nemveer, oakcobalt, peakbolt, pep7siup, qbs, said, savi0ur, tapir, wintermute, zaevlad, zzebra83
7.8372 USDC - $7.84
AMO functions don't sync RdpxV2Core reserves internal accounting when perform operations.
RdpxV2Core broken reserves accounting after Uniswap v3 AMO operations. Its can be fixed with RdpxV2Core.sync function call in another tx, but it's not practical and convenient. And still it can affect the protocol if there are txs between AMO operations and RdpxV2Core.sync txs.
Uniswap v2 AMO don't call RdpxV2Core.sync at all: https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/amo/UniV2LiquidityAmo.sol#L160-L178 Where as Uniswap v3 AMO do it after every operation: https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/amo/UniV3LiquidityAmo.sol#L361 And in Uniswap v3 AMO when collecting fee: https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/amo/UniV3LiquidityAmo.sol#L119-L133
Manual Review
Add RdpxV2Core.sync to UniV2LiquidityAMO._sendTokensToRdpxV2Core
and UniV3LiquidityAMO.collectFees functions
Uniswap
#0 - c4-pre-sort
2023-09-09T03:45:01Z
bytes032 marked the issue as duplicate of #798
#1 - c4-pre-sort
2023-09-09T04:09:38Z
bytes032 marked the issue as duplicate of #269
#2 - c4-pre-sort
2023-09-11T11:58:45Z
bytes032 marked the issue as sufficient quality report
#3 - c4-judge
2023-10-15T18:11:31Z
GalloDaSballo marked the issue as satisfactory
🌟 Selected for report: degensec
Also found by: 0x3b, 0xnev, HChang26, KmanOfficial, QiuhaoLi, T1MOH, WoolCentaur, Yanchuan, ayden, bart1e, jasonxiale, kutugu, mert_eren, nirlin, peakbolt, peanuts, pep7siup, qpzm, tapir, ubermensch, wintermute
12.4133 USDC - $12.41
ReLPContract when performing relp does not send unused WETH back to rdpxV2Core.
Unused WETH not transferred back to reserves and stack in ReLPContract contract.
Amount add min set to 0 on both tokens: https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/reLP/ReLPContract.sol#L286-L295 It means that not all desired A and B tokens can be used. Remainning tokensA are sent back to reserves, but tokenB don't - they are stuck in contract.
Manual Review
Send back both unused tokens. Add this snippet:
IERC20WithBurn(addresses.tokenB).safeTransfer( addresses.rdpxV2Core, IERC20WithBurn(addresses.tokenB).balanceOf(address(this)) );
Token-Transfer
#0 - c4-pre-sort
2023-09-07T12:56:06Z
bytes032 marked the issue as duplicate of #1286
#1 - c4-pre-sort
2023-09-07T12:56:59Z
bytes032 marked the issue as sufficient quality report
#2 - c4-judge
2023-10-18T12:14:48Z
GalloDaSballo marked the issue as partial-50
#3 - GalloDaSballo
2023-10-18T12:14:52Z
Very low quality description