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: 45/183
Findings: 2
Award: $270.44
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Limbooo
Also found by: 0xabhay, 0xleadwizard, AM, ArmedGoose, Evo, HChang26, Infect3d, Jorgect, MiniGlome, SpicyMeatball, TheSchnilch, ahmedaghadi, favelanky, pontifex
238.0297 USDC - $238.03
https://github.com/code-423n4/2024-04-dyad/blob/main/src/core/VaultManagerV2.sol#L119-L153
Users will not be able to withdraw their funds until malicious user stops the DoS.
The current implementation of deposit and withdraw has an idToBlockOfLastDeposit
mapping which doesn't allow to withdrawal of funds if they were deposited in the same block.
No need to be an owner of the dNFT to be able to deposit, see the isValidDNft
modifier. Such implementation allows a malicious user to deposit a small number of tokens whenever the user wants to withdraw. Moreover, a malicious user can create a smart contract that will reflect the Vault interface, to not spend tokens. This is possible because the deposit
function doesn't check the user-provided vault
address.
function deposit(uint256 id, address vault, uint256 amount) external isValidDNft(id) { idToBlockOfLastDeposit[id] = block.number; Vault _vault = Vault(vault); // @med if the token with fee => should track otherwise _vault.asset().safeTransferFrom(msg.sender, address(vault), amount); _vault.deposit(id, amount); }
modifier isValidDNft(uint256 id) { if (dNft.ownerOf(id) == address(0)) revert InvalidDNft(); _; }
https://github.com/code-423n4/2024-04-dyad/blob/main/src/core/VaultManagerV2.sol#L119-L153
Manual Analysis
Consider changing the modifier on the deposit
function to isDnftOwner
.
DoS
#0 - c4-pre-sort
2024-04-27T11:35:26Z
JustDravee marked the issue as duplicate of #1103
#1 - c4-pre-sort
2024-04-27T11:51:43Z
JustDravee marked the issue as duplicate of #489
#2 - c4-pre-sort
2024-04-29T09:28:32Z
JustDravee marked the issue as sufficient quality report
#3 - c4-judge
2024-05-05T20:32:29Z
koolexcrypto marked the issue as not a duplicate
#4 - c4-judge
2024-05-05T20:32:40Z
koolexcrypto marked the issue as duplicate of #1266
#5 - c4-judge
2024-05-11T12:18:56Z
koolexcrypto marked the issue as satisfactory
#6 - c4-judge
2024-05-28T19:12:55Z
koolexcrypto marked the issue as duplicate of #930
🌟 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
https://github.com/code-423n4/2024-04-dyad/blob/cd48c684a58158de444b24854ffd8f07d046c31b/src/core/VaultManagerV2.sol#L134-L153 https://github.com/code-423n4/2024-04-dyad/blob/cd48c684a58158de444b24854ffd8f07d046c31b/src/core/VaultManagerV2.sol#L250-L267
The user will not be able to withdraw a significant amount of Kerosine tokens at once.
The Kerosine token can be used to keep the debt overcollaterized. The main issue is depositing too many of these tokens will result in the unavailability to withdraw them later even if the debt is overcollaterized.
Let's see this in an example:
100$
in Weth and 1000$
in Kerosine tokens (to have overcollaterized debt).dyadMinted = 0
(she didn't mint any dyad tokens yet)value = 1000$
(Kerosine tokens)if (getNonKeroseneValue(id) - value < dyadMinted)
will result in if (100 - 1000 < 0)
which will revert the transaction.If the price of the Kerosine tokens goes up or price of ETH goes down or Alice decides to mint some dyad tokens, the situation will be even worse. The solution is to withdraw small amounts of Kerosine tokens. The number of transactions to complete the withdrawal can be very high. This is not the intended behavior and can significantly affect the user experience.
function withdraw(uint256 id, address vault, uint256 amount, address to) public isDNftOwner(id) { if (idToBlockOfLastDeposit[id] == block.number) revert DepositedInSameBlock(); uint256 dyadMinted = dyad.mintedDyad(address(this), id); Vault _vault = Vault(vault); uint256 value = amount * _vault.assetPrice() * 1e18 / 10 ** _vault.oracle().decimals() / 10 ** _vault.asset().decimals(); // @audit substraction non kerosine value from the kerosine value if (getNonKeroseneValue(id) - value < dyadMinted) revert NotEnoughExoCollat(); _vault.withdraw(id, to, amount); if (collatRatio(id) < MIN_COLLATERIZATION_RATIO) revert CrTooLow(); }
Manual Analysis
If the user wants to withdraw the Kerosine tokens, the if (getNonKeroseneValue(id) - value < dyadMinted)
check should not be used. Only the collaterization ratio should be checked.
Math
#0 - c4-pre-sort
2024-04-26T21:10:30Z
JustDravee marked the issue as duplicate of #397
#1 - c4-pre-sort
2024-04-29T08:48:14Z
JustDravee marked the issue as sufficient quality report
#2 - c4-judge
2024-05-11T19:23:09Z
koolexcrypto marked the issue as satisfactory
#3 - c4-judge
2024-05-13T18:33:04Z
koolexcrypto changed the severity to 3 (High Risk)