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: 149/183
Findings: 2
Award: $3.74
🌟 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#L127 https://github.com/code-423n4/2024-04-dyad/blob/cd48c684a58158de444b24854ffd8f07d046c31b/src/core/VaultManagerV2.sol#L143
<description>An attacker can block a user from withdrawing by front-running the withdraw transaction and depositing 0 amount to the NFT.</description>
In VaultManagerV2.sol:127
, the deposit
function updates the idToBlockOfLastDeposit
mapping with the current block number for the given NFT id
. The withdraw
function at line 143 checks if the idToBlockOfLastDeposit
for the given id
is equal to the current block number, and if so, it reverts the transaction with the "DepositedInSameBlock" error.
An attacker can exploit this by front-running the user's withdrawal transaction and calling the deposit
function with a 0 amount for the same NFT id
. Since there is no check for a minimum deposit this will update the idToBlockOfLastDeposit
mapping to the current block number, causing the user's subsequent withdrawal transaction to revert due to the "DepositedInSameBlock" error.
Manual Review
A simple solution for this would be to have a minimum deposit amount on VaultManagerV2.deposit
function as it would be not profitable for an attacker to lose funds just to revert the user transaction and make them wait for one block.
MEV
MEV
#0 - c4-pre-sort
2024-04-27T11:24:07Z
JustDravee marked the issue as duplicate of #1103
#1 - c4-pre-sort
2024-04-27T11:51:49Z
JustDravee marked the issue as duplicate of #489
#2 - c4-pre-sort
2024-04-29T09:28:45Z
JustDravee marked the issue as sufficient quality report
#3 - c4-judge
2024-05-05T20:38:07Z
koolexcrypto marked the issue as unsatisfactory: Invalid
#4 - c4-judge
2024-05-05T21:09:48Z
koolexcrypto marked the issue as nullified
#5 - c4-judge
2024-05-05T21:09:53Z
koolexcrypto marked the issue as not nullified
#6 - c4-judge
2024-05-08T15:30:03Z
koolexcrypto marked the issue as duplicate of #1001
#7 - c4-judge
2024-05-11T19:45:06Z
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: carrotsmuggler
Also found by: 0xAlix2, 0xSecuri, 0xleadwizard, 0xlemon, 0xtankr, 3th, Aamir, Abdessamed, Bauchibred, Circolors, Egis_Security, Evo, Hueber, Mahmud, SBSecurity, TheSavageTeddy, TheSchnilch, Tychai0s, alix40, bbl4de, btk, d3e4, ducanh2706, falconhoof, itsabinashb, ke1caM, lian886, n4nika, oakcobalt, pontifex, sashik_eth, steadyman, tchkvsky, zhuying
3.7207 USDC - $3.72
https://github.com/code-423n4/2024-04-dyad/blob/cd48c684a58158de444b24854ffd8f07d046c31b/src/core/Vault.kerosine.unbounded.sol#L60 https://github.com/code-423n4/2024-04-dyad/blob/cd48c684a58158de444b24854ffd8f07d046c31b/src/core/VaultManagerV2.sol#L88
In the Kerosene Manager only non-kerosene vaults are allowed, otherwise a recursion is created when calculating the price of Kerosene but then VaultManagerV2 requires the Kerosene vault to be added to the manager before being able to add it as a vault for an NFT.</description>
In VaultManagerV2.sol:74
, the addKerosene
function allows adding Kerosene vaults to the vaultsKerosene
array. However, the assetPrice
function in Vault.kerosine.unbounded.sol
is meant to get only non-Kerosene vaults from the kerosineManager.getVaults()
function. If Kerosene vaults are added to the KeroseneManager, it will create an infinite recursion when vault.assetPrice()
is called within the loop, as the Kerosene vault's assetPrice
function will try to calculate the Kerosene price again, leading to a stack overflow.
// VaultManagerV2.sol function addKerosene(uint256 id, address vault) external isDNftOwner(id) { if (vaultsKerosene[id].length() >= MAX_VAULTS_KEROSENE) revert TooManyVaults(); if (!keroseneManager.isLicensed(vault)) revert VaultNotLicensed(); // Needs Kerosene Manager to have Kerosene Vault added if (!vaultsKerosene[id].add(vault)) revert VaultAlreadyAdded(); emit Added(id, vault); } // Vault.kerosine.unbounded.sol function assetPrice() public view override returns (uint256) { uint256 tvl; address[] memory vaults = kerosineManager.getVaults(); uint256 numberOfVaults = vaults.length; // @audit-info this is meant to get only Non-kerosene vaults, otherwise it will eventually revert when calling the vault.assetPrice() function because of infinite recursion. for (uint256 i = 0; i < numberOfVaults; i++) { Vault vault = Vault(vaults[i]); tvl += vault.asset().balanceOf(address(vault)) * vault.assetPrice() * 1e18 / (10 ** vault.asset().decimals()) / (10 ** vault.oracle().decimals()); } // @audit-info C = tvl, D = dyad.totalSupply, K = kerosineDenominator.denominator // @audit numerator can be negative (revert) if tvl price falls below dyad.totalSupply // @audit-info given that in order to mint dyad a 150% collateral is required, even if nobody uses uint256 numerator = tvl - dyad.totalSupply(); uint256 denominator = kerosineDenominator.denominator(); // @audit-info this assetPrice goes higher if the TVL increases in vaults or if dyad.totalSupply decreases return numerator * 1e8 / denominator; }
Manual Review
The simplest way would be to use a VaultLicenser in VaultManagerV2 instead of KeroseneManager, but special attention must be put in making sure they are in sync regarding the vaults added.
Other
#0 - c4-pre-sort
2024-04-29T07:08:53Z
JustDravee marked the issue as duplicate of #70
#1 - c4-pre-sort
2024-04-29T09:36:59Z
JustDravee marked the issue as sufficient quality report
#2 - c4-judge
2024-05-11T20:01:11Z
koolexcrypto marked the issue as satisfactory