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: 110/189
Findings: 2
Award: $46.26
🌟 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
ethAmount subtracted can be greater than the totalAvailableCollateral.
In PerpetualAtlanticVault.settle function transfer of collateral token occur from perpetual vault to rdpxV2Core further it calling PerpetualAtlanticVaultLP.subtractLoss to subtract ethAmount transfer from vault to rdpxV2Core
IPerpetualAtlanticVaultLP(addresses.perpetualAtlanticVaultLP).subtractLoss( ethAmount );
which is subtracting ethAmount from _totalCollateral in PerpetualAtlanticVaultLP
function subtractLoss(uint256 loss) public onlyPerpVault { require( collateral.balanceOf(address(this)) == _totalCollateral - loss, "Not enough collateral was sent out" ); _totalCollateral -= loss; }
the problem here is that before subtracting it donot check the ethAmount to subtract is greater then the totalCollateral or not like in purchase function it validate the ethAmount should be less and equal to totalAvailableCollateral()
uint256 requiredCollateral = (amount * strike) / 1e8; _validate( requiredCollateral <= perpetualAtlanticVaultLp.totalAvailableCollateral(), 3 );
not checking ethAmount before subtract might revert whole settle function to its initial state.
Manual
Add a validate check before subtracting ethAmount , _validate( requiredCollateral <= perpetualAtlanticVaultLp.totalAvailableCollateral(), 3 );
Invalid Validation
#0 - c4-pre-sort
2023-09-09T10:02:35Z
bytes032 marked the issue as duplicate of #619
#1 - c4-pre-sort
2023-09-11T16:15:17Z
bytes032 marked the issue as sufficient quality report
#2 - c4-judge
2023-10-20T20:02:02Z
GalloDaSballo marked the issue as satisfactory
#3 - c4-judge
2023-10-21T07:26:28Z
GalloDaSballo changed the severity to 3 (High Risk)
#4 - c4-judge
2023-10-21T07:26:28Z
GalloDaSballo changed the severity to 3 (High Risk)
#5 - c4-judge
2023-10-21T07:26:28Z
GalloDaSballo changed the severity to 3 (High Risk)
#6 - c4-judge
2023-10-21T07:26:28Z
GalloDaSballo changed the severity to 3 (High Risk)
#7 - c4-judge
2023-10-21T07:26:28Z
GalloDaSballo changed the severity to 3 (High Risk)
#8 - c4-judge
2023-10-21T07:26:29Z
GalloDaSballo changed the severity to 3 (High Risk)
#9 - c4-judge
2023-10-21T07:26:29Z
GalloDaSballo changed the severity to 3 (High Risk)
🌟 Selected for report: 0xWagmi
Also found by: 836541, Bauchibred, GangsOfBrahmin, Hama, IceBear, Inspecktor, Matin, MohammedRizwan, catellatech, erebus, lsaudit, niki, okolicodes, ravikiranweb3, tapir, vangrim, zaevlad
46.2486 USDC - $46.25
ERC4626 vault share price can be maliciously inflated on the initial deposit, leading to the next depositor losing assets due to precision issues.
The first depositor of an ERC4626 vault can maliciously manipulate the share price by depositing the lowest possible amount (1 wei) of liquidity and then artificially inflating ERC4626.totalAssets.
This can inflate the base share price as high as 1:1e18 early on, which force all subsequence deposit to use this share price as a base and worst case, due to rounding down, if this malicious initial deposit front-run someone else depositing, this depositor will receive 0 shares and lost his deposited assets.
Given a vault with DAI as the underlying asset:
Alice (attacker) deposits initial liquidity of 1 wei DAI via deposit() Alice receives 1e18 (1 wei) vault shares Alice transfers 1 ether of DAI via transfer() to the vault to artificially inflate the asset balance without minting new shares. The asset balance is now 1 ether + 1 wei DAI -> vault share price is now very high (= 1000000000000000000001 wei ~ 1000 * 1e18) Bob (victim) deposits 100 ether DAI Bob receives 0 shares Bob receives 0 shares due to a precision issue. His deposited funds are lost.
The shares are calculated as following return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets()); In case of a very high share price, due to totalAssets() > assets * supply, shares will be 0.
Manual Review
This is a well-known issue, Uniswap and other protocols had similar issues when supply == 0.
For the first deposit, mint a fixed amount of shares, e.g. 10**decimals()
return 10**decimals; } else { return assets.mulDivDown(supply, totalAssets()); }
ERC4626
#0 - c4-pre-sort
2023-09-07T13:30:40Z
bytes032 marked the issue as duplicate of #863
#1 - c4-pre-sort
2023-09-11T09:10:18Z
bytes032 marked the issue as sufficient quality report
#2 - c4-judge
2023-10-18T12:50:44Z
GalloDaSballo marked the issue as satisfactory