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: 80/183
Findings: 3
Award: $39.73
🌟 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/cd48c684a58158de444b24854ffd8f07d046c31b/src/core/VaultManagerV2.sol#L119 https://github.com/code-423n4/2024-04-dyad/blob/cd48c684a58158de444b24854ffd8f07d046c31b/src/core/VaultManagerV2.sol#L134
In vaultManagerV2.sol,any one can call deposit function to deposit any amount asset to the vault. However, withdraw function will be revert in [1] once the deposit function was frontrun with same id in the same block. Thus Attacker can frontrun a deposit request with amount 0 to block the withdraw reqeust. And if the attacker want, no one can withdraw funds from the vault.
function withdraw( uint id, address vault, uint amount, address to ) public isDNftOwner(id) { if (idToBlockOfLastDeposit[id] == block.number) revert DepositedInSameBlock(); -----------[1] .... }
VS
Set a whitelist for deposit function. The nft owner can decide who can call the deposit function.
Access Control
#0 - c4-pre-sort
2024-04-27T11:34:02Z
JustDravee marked the issue as duplicate of #1103
#1 - c4-pre-sort
2024-04-27T11:45:53Z
JustDravee marked the issue as duplicate of #489
#2 - c4-pre-sort
2024-04-29T09:32:36Z
JustDravee marked the issue as sufficient quality report
#3 - c4-judge
2024-05-05T20:38:09Z
koolexcrypto marked the issue as unsatisfactory: Invalid
#4 - c4-judge
2024-05-05T21:15:28Z
koolexcrypto marked the issue as nullified
#5 - c4-judge
2024-05-05T21:15:32Z
koolexcrypto marked the issue as not nullified
#6 - c4-judge
2024-05-08T15:29:22Z
koolexcrypto marked the issue as duplicate of #1001
#7 - c4-judge
2024-05-11T19:44:36Z
koolexcrypto marked the issue as satisfactory
🌟 Selected for report: 0xAlix2
Also found by: 0xfox, 0xlemon, 0xnev, 3docSec, Aamir, Abdessamed, Dudex_2004, Egis_Security, Evo, FastChecker, Honour, Jorgect, KupiaSec, Limbooo, MrPotatoMagic, SpicyMeatball, TheSchnilch, alix40, bhilare_, favelanky, forgebyola, ke1caM, kennedy1030, koo, oakcobalt, petro_1912, shikhar229169
32.4128 USDC - $32.41
Withdraw function should guarantee the usd value of NonKerosene asset is higher than dyadminted. Thus we have the check in [1]. However, if user want to withdraw Kerosene asset. We should only check
if(getNonKeroseneValue(id) < dyadMinted) revert NotEnoughExoCollat();
rather than
if (getNonKeroseneValue(id) - value < dyadMinted) revert NotEnoughExoCollat();
function withdraw( uint id, address vault, uint amount, address to ) public isDNftOwner(id) { if (idToBlockOfLastDeposit[id] == block.number) revert DepositedInSameBlock(); uint dyadMinted = dyad.mintedDyad(address(this), id); Vault _vault = Vault(vault); uint value = amount * _vault.assetPrice() * 1e18 / 10**_vault.oracle().decimals() / 10**_vault.asset().decimals(); if (getNonKeroseneValue(id) - value < dyadMinted) revert NotEnoughExoCollat(); -------------------[1] _vault.withdraw(id, to, amount); if (collatRatio(id) < MIN_COLLATERIZATION_RATIO) revert CrTooLow(); }
vs
If the user withdraw Kerosene asset. The check in [1] should be
if(getNonKeroseneValue(id) < dyadMinted) revert NotEnoughExoCollat();
Context
#0 - c4-pre-sort
2024-04-29T07:11:35Z
JustDravee marked the issue as insufficient quality report
#1 - c4-judge
2024-05-10T20:13:40Z
koolexcrypto marked the issue as duplicate of #397
#2 - c4-judge
2024-05-11T19:22:56Z
koolexcrypto marked the issue as satisfactory
🌟 Selected for report: 0xAlix2
Also found by: 0x175, 0x486776, 0xnev, 3docSec, 3th, Aamir, Abdessamed, AlexCzm, Angry_Mustache_Man, Circolors, DedOhWale, Emmanuel, Giorgio, Honour, Jorgect, KupiaSec, Maroutis, Myrault, SBSecurity, Stefanov, T1MOH, VAD37, Vasquez, adam-idarrha, alix40, ducanh2706, falconhoof, iamandreiski, ke1caM, kennedy1030, koo, lian886, ljj, miaowu, pontifex, sashik_eth, shikhar229169, vahdrak1
7.3026 USDC - $7.30
The liquadate function in VaultManagerV2.sol only transfer the vaults to the liquidator in [1]. However, it ignore the vaultsKerosene. Which makes liquidator get less asset in liquidation than they should get.
function liquidate( uint id, uint to ) external isValidDNft(id) isValidDNft(to) { uint cr = collatRatio(id); if (cr >= MIN_COLLATERIZATION_RATIO) revert CrTooHigh(); dyad.burn(id, msg.sender, dyad.mintedDyad(address(this), id)); uint cappedCr = cr < 1e18 ? 1e18 : cr; uint liquidationEquityShare = (cappedCr - 1e18).mulWadDown(LIQUIDATION_REWARD); uint liquidationAssetShare = (liquidationEquityShare + 1e18).divWadDown(cappedCr); uint numberOfVaults = vaults[id].length(); ---------------[1] for (uint i = 0; i < numberOfVaults; i++) { Vault vault = Vault(vaults[id].at(i)); uint collateral = vault.id2asset(id).mulWadUp(liquidationAssetShare); vault.move(id, to, collateral); } emit Liquidate(id, msg.sender, to); }
vs
Add a for loop to transfer the asset in vaultsKerosene.
Context
#0 - c4-pre-sort
2024-04-28T10:22:28Z
JustDravee marked the issue as duplicate of #128
#1 - c4-pre-sort
2024-04-29T09:07:12Z
JustDravee marked the issue as sufficient quality report
#2 - c4-judge
2024-05-11T19:40:00Z
koolexcrypto marked the issue as satisfactory