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: 117/183
Findings: 2
Award: $7.37
🌟 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#L127 https://github.com/code-423n4/2024-04-dyad/blob/main/src/core/VaultManagerV2.sol#L143
Attacker can prevent owners from withdrawing without actually depositing any amount since vault address isn't validated and can be any address including the attacker own custom vault contract. Therefore at zero cost.
The withdraw() function implements a mechanism to prevent flashloan attack issue by the Id last deposited when withdrawing:
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(); _vault.withdraw(id, to, amount); if (collatRatio(id) < MIN_COLLATERIZATION_RATIO) revert CrTooLow(); }
This last deposit mapping is updated on the deposit function:
function deposit( uint id, address vault, uint amount ) external isValidDNft(id) { idToBlockOfLastDeposit[id] = block.number; Vault _vault = Vault(vault); _vault.asset().safeTransferFrom(msg.sender, address(vault), amount); _vault.deposit(id, amount); }
Notice from the above function shown, there where no access control or permission required to deposited for any valid Id, also notice there are no license check for the vault to be deposited. This means an attacker can prevent owners from withdrawing without actually depositing any amount since vault address isn't validated and can be any address including the attacker own custom vault contract, and since there are no permission needed, can frontrun whenever attempts to withdraw and update the lastdeposited to the same block.number as the withdraw transaction.
Manual review
Implement an access control mechanism to allow only addresses with the owner's permission/allowance.
Access Control
#0 - c4-pre-sort
2024-04-27T11:35:03Z
JustDravee marked the issue as duplicate of #1103
#1 - c4-pre-sort
2024-04-27T11:45:57Z
JustDravee marked the issue as duplicate of #489
#2 - c4-pre-sort
2024-04-29T09:31:34Z
JustDravee marked the issue as sufficient quality report
#3 - c4-judge
2024-05-05T20:38:08Z
koolexcrypto marked the issue as unsatisfactory: Invalid
#4 - c4-judge
2024-05-05T21:11:32Z
koolexcrypto marked the issue as nullified
#5 - c4-judge
2024-05-05T21:11:41Z
koolexcrypto marked the issue as not nullified
#6 - c4-judge
2024-05-08T15:29:28Z
koolexcrypto marked the issue as duplicate of #1001
#7 - c4-judge
2024-05-11T19:44:50Z
koolexcrypto marked the issue as satisfactory
🌟 Selected for report: TheSavageTeddy
Also found by: 0x175, 0x486776, 0xnev, AamirMK, AlexCzm, ArmedGoose, BiasedMerc, CaeraDenoir, Egis_Security, Jorgect, KYP, MrPotatoMagic, PoeAudits, SBSecurity, SovaSlava, VAD37, adam-idarrha, alix40, carrotsmuggler, d_tony7470, dimulski, grearlake, josephdara, ljj, n0kto, okolicodes, sashik_eth, sil3th, turvy_fuzz
7.3512 USDC - $7.35
https://github.com/code-423n4/2024-04-dyad/blob/main/src/core/VaultManagerV2.sol#L101 https://github.com/code-423n4/2024-04-dyad/blob/main/src/core/VaultManagerV2.sol#L113
Attackers can prevent DNftOwners from removing vaults from their Id.
Here are the remove functions:
function remove( uint id, address vault ) external isDNftOwner(id) { @> if (Vault(vault).id2asset(id) > 0) revert VaultHasAssets(); if (!vaults[id].remove(vault)) revert VaultNotAdded(); emit Removed(id, vault); }
function removeKerosene( uint id, address vault ) external isDNftOwner(id) { @> if (Vault(vault).id2asset(id) > 0) revert VaultHasAssets(); if (!vaultsKerosene[id].remove(vault)) revert VaultNotAdded(); emit Removed(id, vault); }
Notice they both check if the vault still has assets in them before allowing them to be removed. These assets can added to the vault through the deposit function with any amount even as little as 1 unit of the token:
function deposit( uint id, address vault, uint amount ) external isValidDNft(id) { idToBlockOfLastDeposit[id] = block.number; Vault _vault = Vault(vault); _vault.asset().safeTransferFrom(msg.sender, address(vault), amount); @> _vault.deposit(id, amount); }
The issue here is that as we can see, the deposit function has no access control meaning anyone can add access to the vault including when an owner attempts to remove the vault after withdrawing, frontrunning the transition and depositing an insignificant amount to prevent the owner from removing vaults.
Manual Review
Either consider allowing owners to choose to remove vault even if assets are in them, they can still be added back or implement an access control or permission allowance from the Id owners to deposit for them.
DoS
#0 - c4-pre-sort
2024-04-29T07:44:38Z
JustDravee marked the issue as duplicate of #489
#1 - c4-pre-sort
2024-04-29T09:31:34Z
JustDravee marked the issue as sufficient quality report
#2 - c4-judge
2024-05-05T20:33:23Z
koolexcrypto marked the issue as not a duplicate
#3 - c4-judge
2024-05-06T11:31:21Z
koolexcrypto marked the issue as duplicate of #118
#4 - c4-judge
2024-05-11T12:24:22Z
koolexcrypto marked the issue as satisfactory
#5 - c4-judge
2024-05-13T18:37:20Z
koolexcrypto changed the severity to 2 (Med Risk)