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: 128/189
Findings: 2
Award: $19.24
🌟 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
The state variable totalWethDelegated
does not track correctly the total amount of WETH
delegated, because it is not updated in the withdraw
function.
In the file RdpxV2Core.sol
there is a function withdraw
, which lets the caller withdraw
the unused collateral from a delegatePosition
he created. The unused collateral is calculated as:
amountWithdrawn = delegate.amount - delegate.activeCollateral;
After that the amountWithdrawn
is sent to the caller:
IERC20WithBurn(weth).safeTransfer(msg.sender, amountWithdrawn);
Since the caller takes amountWithdrawn
back, the total amount of WETH
delegated is decreased by amountWithdrawn
and the state variable tracking the total amount of WETH
delegated should be updated like so:
totalWethDelegated -= amountWithdrawn;
However, the withdraw
function is missing the line:
totalWethDelegated -= amountWithdrawn;
which leads to a bug. As a result, the state variable totalWethDelegated
does not show correctly the amount of WETH
that is delegated.
Manual review
Add the following line to the withdraw
function:
totalWethDelegated -= amountWithdrawn;
After the withdraw
function is fixed, it should look like:
function withdraw( uint256 delegateId ) external returns (uint256 amountWithdrawn) { _whenNotPaused(); _validate(delegateId < delegates.length, 14); Delegate storage delegate = delegates[delegateId]; _validate(delegate.owner == msg.sender, 9); amountWithdrawn = delegate.amount - delegate.activeCollateral; _validate(amountWithdrawn > 0, 15); delegate.amount = delegate.activeCollateral; totalWethDelegated -= amountWithdrawn; IERC20WithBurn(weth).safeTransfer(msg.sender, amountWithdrawn); emit LogDelegateWithdraw(delegateId, amountWithdrawn); }
Error
#0 - c4-pre-sort
2023-09-08T13:27:54Z
bytes032 marked the issue as duplicate of #2186
#1 - c4-judge
2023-10-20T17:52:47Z
GalloDaSballo marked the issue as satisfactory
#2 - c4-judge
2023-10-21T07:38:54Z
GalloDaSballo changed the severity to 3 (High Risk)
#3 - c4-judge
2023-10-21T07:40:44Z
GalloDaSballo marked the issue as partial-50
🌟 Selected for report: juancito
Also found by: 0xDING99YA, 0xTiwa, 0xkazim, 0xnev, ABA, ArmedGoose, Aymen0909, Bauchibred, Evo, IceBear, KrisApostolov, MohammedRizwan, Nikki, QiuhaoLi, T1MOH, Toshii, WoolCentaur, Yanchuan, __141345__, asui, bart1e, carrotsmuggler, catellatech, chaduke, codegpt, deadrxsezzz, degensec, dethera, dirk_y, erebus, ether_sky, gjaldon, glcanvas, jasonxiale, josephdara, klau5, kodyvim, ladboy233, lsaudit, minhquanym, parsely, peakbolt, pep7siup, rvierdiiev, said, savi0ur, sces60107, tapir, ubermensch, volodya, zzebra83
19.1724 USDC - $19.17
https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/decaying-bonds/RdpxDecayingBonds.sol#L135-L145 https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/decaying-bonds/RdpxDecayingBonds.sol#L144 https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/core/RdpxV2Core.sol#L643-L646
Potentially, the impact can be catastrophic - with the current implementation, the caller of the function decreaseAmount
may unintentionally increase the bond amount thinking the bond amount is decreased.
In the file RdpxDecayingBonds.sol
there is a function decreaseAmount
, which is expected to decrease the bond amount of a specific bond. However, the logic that 'decreases' the amount is implemented as:
bonds[bondId].rdpxAmount = amount;
There are no checks in place to verify that bonds[bondId].rdpxAmount > amount
. This implementation puts severe burden on the caller of the function decreaseAmount
- the caller should always know what the value of bonds[bondId].rdpxAmount
is in order to specify amount
in such a way that bonds[bondId].rdpxAmount > amount
, which is insanely error-prone. The caller of the function decreaseAmount
, not aware what the value of bonds[bondId].rdpxAmount
is, may call the function with amount
such that bonds[bondId].rdpxAmount < amount
, the line:
bonds[bondId].rdpxAmount = amount;
will execute. As a result of the call to the function decreaseAmount
, the value of bonds[bondId].rdpxAmount
increases.
Manual review
The function can be fixed in several ways:
require
check at the beginning of the function to make sure that bonds[bondId].rdpxAmount > amount
. This will make sure that after every successful call to decreaseAmount
the value of bonds[bondId].rdpxAmount
will truly decrease.function decreaseAmount( uint256 bondId, uint256 amount ) public onlyRole(RDPXV2CORE_ROLE) { _whenNotPaused(); require(bonds[bondId].rdpxAmount > amount, "Error, amount should be less than bonds[bondId].rdpxAmount"); bonds[bondId].rdpxAmount = amount; }
amount
as the amount that will be subtracted from bonds[bondId].rdpxAmount
, thus decreasing the value of bonds[bondId].rdpxAmount
.function decreaseAmount( uint256 bondId, uint256 amount ) public onlyRole(RDPXV2CORE_ROLE) { _whenNotPaused(); bonds[bondId].rdpxAmount -= amount; }
Invalid Validation
#0 - c4-pre-sort
2023-09-09T11:52:33Z
bytes032 marked the issue as duplicate of #740
#1 - c4-pre-sort
2023-09-11T07:45:25Z
bytes032 marked the issue as sufficient quality report
#2 - c4-judge
2023-10-20T19:53:25Z
GalloDaSballo changed the severity to QA (Quality Assurance)