Dopex - ether_sky's results

A rebate system for option writers in the Dopex Protocol.

General Information

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

Dopex

Findings Distribution

Researcher Performance

Rank: 107/189

Findings: 3

Award: $58.67

QA:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/core/RdpxV2Core.sol#L975-L1008

Vulnerability details

Impact

One user add delegate by calling addToDelegate() function with some weth. After some time, that user withdraw the remaining weth by calling withdraw() function. The problem here is that totalWethDelegated variable is updated only in addToDelegate() function not in withdraw(). And call sync() function. Then reserveAsset[reservesIndex["WETH"]].tokenBalance is updated incorrectly and once it has done, it is not revertable.

Proof of Concept

please add below function to 'tests/rdpxV2-core/Unit.t.sol' and run 'forge test'.

function testTotalWethDelegated() public { rdpxV2Core.bond(10 * 1e18, 0, address(this)); uint256 userBalanceBeforeDelegate = weth.balanceOf(address(rdpxV2Core)); (, uint256 wethReserveBeforeDelegate, ) = rdpxV2Core .getReserveTokenInfo("WETH"); // reserveAsset[reservesIndex["WETH"]].tokenBalance > 1e18 assertGt(wethReserveBeforeDelegate, 1e18); rdpxV2Core.addToDelegate(1 * 1e18, 10e8); uint256 userBalanceAfterDelegate = weth.balanceOf(address(rdpxV2Core)); (, uint256 wethReserveAfterDelegate, ) = rdpxV2Core.getReserveTokenInfo( "WETH" ); // real balance changes, but reserveAsset[reservesIndex["WETH"]].tokenBalance doesn't change assertEq(userBalanceAfterDelegate, userBalanceBeforeDelegate + 1e18); assertEq(wethReserveBeforeDelegate, wethReserveAfterDelegate); rdpxV2Core.withdraw(0); (, uint256 wethReserveAfterWithdraw, ) = rdpxV2Core.getReserveTokenInfo( "WETH" ); // reserveAsset[reservesIndex["WETH"]].tokenBalance doesn't change assertEq(wethReserveBeforeDelegate, wethReserveAfterWithdraw); rdpxV2Core.sync(); (, uint256 wethReserveAfterSync, ) = rdpxV2Core.getReserveTokenInfo( "WETH" ); /** 1e18 was removed from 'reserveAsset[reservesIndex["WETH"]].tokenBalance' because 'totalWethDelegated' didn't change when 'withdraw' delegate. This is obviously error. */ assertEq(wethReserveAfterSync, wethReserveAfterWithdraw - 1e18); }

Tools Used

Manual audit

Should add below code to withdraw() function.

totalWethDelegated -= amountWithdrawn;

Assessed type

Error

#0 - c4-pre-sort

2023-09-07T08:19:20Z

bytes032 marked the issue as duplicate of #2186

#1 - c4-judge

2023-10-20T17:52:57Z

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:25Z

GalloDaSballo marked the issue as partial-50

Findings Information

Awards

39.433 USDC - $39.43

Labels

bug
2 (Med Risk)
satisfactory
sufficient quality report
duplicate-1805

External Links

Lines of code

https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/reLP/ReLPContract.sol#L273-L275

Vulnerability details

Impact

If the rDPX price is higher than EDH (if possible), the expected amount of token A cannot be exchanged because this incorrect value is higher than the correct value. This means it violates the reLP logic.

Since rDPX prices are usually much lower than EDH, this incorrect value is less than the correct value, so you can swap less than you expect.

Proof of Concept

tokenBAmount = tokenAAmount * tokenAPrice / 1e8 tokenAAmount = tokenBAmount * 1e8 / tokenAPrice

For example: tokenAPrice = 1e6 (i.e. 1 tokenB = 100 tokenA ) And we want to swap 1e18 tokenB for tokenA. (We are gonna ignore slippage.) The calculated value in code : tokenA = tokenB * tokenAPrice / 1e8 = 1e18 * 1e6 / 1e8 = 1e16 This means that token A is more valuable than tokenB. Actual value will be tokenB * 1e8 / tokenAPrice = 1e20

Tools Used

Manual audit

mintokenAAmount = (((amountB / 2) * 1e8) / tokenAInfo.tokenAPrice) - (((amountB / 2) * 1e8) / tokenAInfo.tokenAPrice) * slippageTolerance / 1e8;

Assessed type

Error

#0 - c4-pre-sort

2023-09-10T10:41:37Z

bytes032 marked the issue as duplicate of #1805

#1 - c4-pre-sort

2023-09-11T07:04:44Z

bytes032 marked the issue as sufficient quality report

#2 - c4-judge

2023-10-20T09:23:53Z

GalloDaSballo marked the issue as satisfactory

Awards

19.1724 USDC - $19.17

Labels

bug
downgraded by judge
grade-b
QA (Quality Assurance)
satisfactory
sufficient quality report
edited-by-warden
duplicate-1868
Q-21

External Links

Lines of code

https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/core/RdpxV2Core.sol#L1192-L1194

Vulnerability details

Impact

When the 'nextFundingPaymentTimestamp()' is less than 'block.timestamp', we can't bond due to we get 'Arithmetic over/underflow'. As far as I understood, the 'latestFundingPaymentPointer' doesn't be updated automatically. In order to bond, the 'latestFundingPaymentPointer' should be updated in Vault.

Proof of Concept

Please add below function to 'tests/rdpxV2-core/Unit.t.sol' and run 'forge test'.

function testBondInNextEpoch() public { vault.updateFundingPaymentPointer(); // move to future epoch, 'latestFundingPaymentPointer' didn't be updated yet. skip(2 * vault.fundingDuration()); // failed with 'Arithmetic over/underflow' error. rdpxV2Core.bond(1 * 1e18, 0, address(this)); }

Tools Used

Manual audit

Add below line to 'IPerpetualAtlanticVault'.

function updateFundingPaymentPointer() external;

And add below lines before calling calculateBondCost() function in the core.

IPerpetualAtlanticVault(addresses.perpetualAtlanticVault) .updateFundingPaymentPointer();

Assessed type

Under/Overflow

#0 - c4-pre-sort

2023-09-10T12:06:07Z

bytes032 marked the issue as duplicate of #1793

#1 - c4-pre-sort

2023-09-11T07:22:44Z

bytes032 marked the issue as sufficient quality report

#2 - c4-judge

2023-10-15T18:24:18Z

GalloDaSballo marked the issue as satisfactory

#3 - c4-judge

2023-10-26T11:19:31Z

GalloDaSballo changed the severity to QA (Quality Assurance)

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter