DYAD - djxploit'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: 173/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/main/src/core/VaultManagerV2.sol#L143

Vulnerability details

Impact

In the VaultManagerV2.sol contract, when a user tries to withdraw his collateral by calling withdraw, an attacker can make the call revert by front-running.

Attacker will front-run the victim's withdraw call, and call the deposit function with same DNFT id passed in the victim's withdraw call, with 0 amount, and same vault address. Due to this, the deposit function will set the idToBlockOfLastDeposit[id] to the current block.number. And as the amount passed by the attacker is 0 amount, so the attacker doesn't need to approve the safetransferFrom call, and it will simply pass. The _vault.deposit line will also simply add 0 to the id2asset[id].

Now finally when the victim's withdraw call will execute, it will revert because of the 1st if statement

`if (idToBlockOfLastDeposit[id] == block.number) revert DepositedInSameBlock();`

As due to front-running by the attacker, the idToBlockOfLastDeposit[id] is set to the current block number, so the if check will return True , and this will revert the victim's withdraw transaction.

Attacker can use this same front-running technique to revert the victim's redeemDyad call too, as the root cause is same. So when the victim calls redeemDyad, attacker will front-run it, and call deposit function with same id and 0 amount. This will update the idToBlockOfLastDeposit[id] to current block number, and due to this the if condition will pass in withdraw function called inside redeemDyad function , and it will revert. Hence the whole transaction will revert.

Thus an attacker can repeat this process of front-running, and prevent the victim from withdrawing his collateral. This will ultimately lead to a DOS-like situation, where the victim will never be able to withdraw his collateral, and his collateral will forever be locked.

Proof of Concept

Consider the below scenerio:

  1. Victim calls withdraw function to withdraw his collateral, by giving the DNFT id and the amount to withdraw, with the vault address
  2. Attacker see this call in mempool, and front-runs it, and calls deposit function
  3. Attacker calls the deposit function, with the same id passed in the victim's withdraw call, and passing 0 amount and with same vault address.
  4. This will update the idToBlockOfLastDeposit[id] to current block number.
  5. Hence when the victim's withdraw call will execute, it will revert, as the if condition will be true.

Tools Used

Manual review

It is recommended to use the isDNftOwner(id) modifier in deposit function, instead of isValidDNft(id)

Assessed type

Other

#0 - c4-pre-sort

2024-04-27T11:35:14Z

JustDravee marked the issue as duplicate of #1103

#1 - c4-pre-sort

2024-04-27T11:45:58Z

JustDravee marked the issue as duplicate of #489

#2 - c4-pre-sort

2024-04-29T09:28:34Z

JustDravee marked the issue as sufficient quality report

#3 - c4-judge

2024-05-05T20:34:06Z

koolexcrypto marked the issue as not a duplicate

#4 - c4-judge

2024-05-06T11:31:45Z

koolexcrypto marked the issue as duplicate of #489

#5 - c4-judge

2024-05-08T15:29:29Z

koolexcrypto marked the issue as duplicate of #1001

#6 - c4-judge

2024-05-11T19:44:52Z

koolexcrypto marked the issue as satisfactory

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