DYAD - darksnow'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: 102/183

Findings: 2

Award: $9.74

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

4.8719 USDC - $4.87

Labels

bug
2 (Med Risk)
satisfactory
sufficient quality report
edited-by-warden
:robot:_11_group
duplicate-175

External Links

Lines of code

https://github.com/code-423n4/2024-04-dyad/blob/cd48c684a58158de444b24854ffd8f07d046c31b/src/core/VaultManagerV2.sol#L217-L219

Vulnerability details

Impact

The liquidation reward is 20% of the remaining collateral above the insolvency threshold, which means that it decreases as the amount of excess collateral diminishes.

If the position up for liquidation is not big enough, it may not be worthwhile for a user to liquidate another position due to the gas costs involved.

It is not uncommon for ETH to experience a drop of 20-30% in minutes. In such cases, positions that were slightly above the minimum collateral ratio could quickly approach near insolvency.

This scenario could lead to significant bad debt and potentially be destructive for the entire protocol, especially since there are no mechanisms in place to recover it.

Proof of Concept

Liquidation reward by descending collateral ratio test:

function testLiquidationReward() public {
    _testLiquidationReward(1.4e18);
    _testLiquidationReward(1.3e18);
    _testLiquidationReward(1.2e18);
    _testLiquidationReward(1.1e18);
    _testLiquidationReward(1.0e18);
}

function _testLiquidationReward(uint256 cr) private {
    uint256 shares20 = _liquidate(cr, 0.2e18); // liquidation with hypothetical 20% reward
    uint256 shares0 = _liquidate(cr, 0); // liquidation with 0 reward
    console.log("\nreward calculation with cr: ", cr);
    console.log("shares with 20%% reward: ", shares20);
    console.log("shares with 0 reward: ", shares0);
    console.log("real liquidation reward (1/10000): ", (shares20 - shares0) * 10000 / shares0);
}

function _liquidate(uint256 cr, uint256 liquidationReward) private returns (uint256 liquidationAssetShare) {
    uint256 cappedCr = cr < 1e18 ? 1e18 : cr;
    uint256 liquidationEquityShare = (cappedCr - 1e18).mulWadDown(liquidationReward);
    liquidationAssetShare = (liquidationEquityShare + 1e18).divWadDown(cappedCr);
}

Results:

[PASS] testLiquidationReward() (gas: 22979)
Logs:

reward calculation with cr:  1400000000000000000
  shares with 20% reward:  771428571428571428
  shares with 0 reward:  714285714285714285
  real liquidation reward (1/10000):  800

reward calculation with cr:  1300000000000000000
  shares with 20% reward:  815384615384615384
  shares with 0 reward:  769230769230769230
  real liquidation reward (1/10000):  600

reward calculation with cr:  1200000000000000000
  shares with 20% reward:  866666666666666666
  shares with 0 reward:  833333333333333333
  real liquidation reward (1/10000):  399

reward calculation with cr:  1100000000000000000
  shares with 20% reward:  927272727272727272
  shares with 0 reward:  909090909090909090
  real liquidation reward (1/10000):  200

reward calculation with cr:  1000000000000000000
  shares with 20% reward:  1000000000000000000
  shares with 0 reward:  1000000000000000000
  real liquidation reward (1/10000):  0

Use case:

  • users have postion with WETH as collateral and a collateral ratio of 160% (e.g. 1600 USD ETH and 1000 USD DYAD minted)
  • ETH drops 30%
  • collateral ratio is now 112% (1120 USD ETH and 1000 USD DYAD minted)
  • the liquidation reward is near 2% that is not enough to cover gas cost for small/medium position liquidations

Tools Used

Manual review.

It might be worth reconsidering the liquidation reward mechanism and thinking about how to manage potential bad debt.

Traditional lending protocols have measures in place to mitigate the risks associated with insolvent accounts that have accumulated bad debt. See here.

Assessed type

Other

#0 - c4-pre-sort

2024-04-27T17:34:16Z

JustDravee marked the issue as duplicate of #1258

#1 - c4-pre-sort

2024-04-29T09:21:20Z

JustDravee marked the issue as sufficient quality report

#2 - c4-judge

2024-05-03T14:07:47Z

koolexcrypto changed the severity to QA (Quality Assurance)

#3 - c4-judge

2024-05-12T09:32:48Z

koolexcrypto marked the issue as grade-c

#4 - fedebianu

2024-05-16T06:58:58Z

My concern extends beyond the issue of small/dust positions as highlighted in https://github.com/code-423n4/2024-04-dyad-findings/issues/1258. More critically, it involves medium-sized positions that can rapidly transition from being healthy to nearing insolvency.

e.g. if liquidation costs ~50$ with a ~2% bonus all position below ~2500$ are at risk to not being liquidated.

Based on my experience in DeFi, most positions within a protocol are typically of medium size. Should a significant number of these medium positions be at risk, the impact could be analogous to https://github.com/code-423n4/2024-04-dyad-findings/issues/1097, where a large position fails to be liquidated.

I believe this issue should retain the initially assigned severity level, or at the very least be classified as medium, because in an extreme situation liquidation could still be performed by someone willing to incur a loss in order to prevent the accumulation of bad debt.

#5 - c4-judge

2024-05-22T14:26:07Z

This previously downgraded issue has been upgraded by koolexcrypto

#6 - koolexcrypto

2024-05-22T15:25:36Z

Hi @fedebianu

Thank you for your feedback.

Already upgraded with the other dups.

#7 - c4-judge

2024-05-28T16:51:48Z

koolexcrypto marked the issue as satisfactory

#8 - c4-judge

2024-05-28T20:06:08Z

koolexcrypto marked the issue as duplicate of #175

Awards

4.8719 USDC - $4.87

Labels

bug
2 (Med Risk)
downgraded by judge
satisfactory
sufficient quality report
edited-by-warden
:robot:_67_group
duplicate-67

External Links

Lines of code

https://github.com/code-423n4/2024-04-dyad/blob/cd48c684a58158de444b24854ffd8f07d046c31b/src/core/Vault.kerosine.unbounded.sol#L50-L69

Vulnerability details

Impact

KEROSENE price is directly related to the exogeneous collateral TVL and is calculated with the following formula: $K = (TVL - DYADsupply) / Ksupply$

If some users are near liquidation threshold, a whale can manipulate the price of KEROSENE, depositing and withdrawing an high amount of collateral, to liquidate them.

Proof of Concept

  • e.g. exo TVL is 2m and dyad minted is 1m
  • whale deposit 200 eth (600k USD) of collateral that is 60% of $TVL - DYADsupply$
  • regular users do normal stuff and deposit KEROSENE to mint DYAD
  • whale withdraw 200 eth and the deterministic value of KEROSENE collapse of nearly 40% causing the liquidation of some positions
  • whale liquidates users and takes profit

Tools Used

Manual review.

An idea might be to gradually update the KEROSENE value, rather than making an immediate change.

Assessed type

Other

#0 - c4-pre-sort

2024-04-28T06:12:27Z

JustDravee marked the issue as duplicate of #67

#1 - c4-pre-sort

2024-04-29T09:17:58Z

JustDravee marked the issue as sufficient quality report

#2 - c4-judge

2024-05-05T09:59:11Z

koolexcrypto changed the severity to 2 (Med Risk)

#3 - c4-judge

2024-05-08T11:50:07Z

koolexcrypto marked the issue as unsatisfactory: Invalid

#4 - c4-judge

2024-05-08T12:48:54Z

koolexcrypto marked the issue as satisfactory

Awards

4.8719 USDC - $4.87

Labels

bug
2 (Med Risk)
satisfactory
sufficient quality report
:robot:_67_group
duplicate-67

External Links

Lines of code

https://github.com/code-423n4/2024-04-dyad/blob/cd48c684a58158de444b24854ffd8f07d046c31b/src/core/Vault.kerosine.unbounded.sol#L50-L69

Vulnerability details

Impact

KEROSENE price is directly related to the exogeneous collateral TVL and is calculated with the following formula: $K = (TVL - DYADsupply) / Ksupply$

If a user try to liquidate a position, a whale can front-run the transaction depositing an high amount of collateral, increasing the value of KEROSENE and thus preventing liquidation. It can then withdraw his deposit and mantain the user's position with a collateral ratio under 150%.

This is a griefing attack that did not generate a profit but can be done to damage the protocol,

Proof of Concept

  • exo TVL is 2m / dyad minted is 1m
  • a (or many) user's position containing KEROSENE collateral ratio falls under 150%
  • another user initiate a transaction to liquidate the position
  • whale deposit 200 eth (600k USD) of collateral that is 60% of $TVL - DYADsupply$ and increase the collateral ratio
  • user's tx fails
  • whale withdraw 200 eth
  • whale prevents liquidation and the faulty user can mantain a collateral ratio under 150%

Tools Used

Manual review.

An idea might be to gradually update the KEROSENE value, rather than making an immediate change.

Assessed type

DoS

#0 - c4-pre-sort

2024-04-28T05:54:00Z

JustDravee marked the issue as duplicate of #67

#1 - JustDravee

2024-04-28T05:54:19Z

Opposite impact of what I'm duping but same root cause

#2 - c4-pre-sort

2024-04-29T09:18:02Z

JustDravee marked the issue as sufficient quality report

#3 - c4-judge

2024-05-08T11:50:06Z

koolexcrypto marked the issue as unsatisfactory: Invalid

#4 - c4-judge

2024-05-08T12:53:55Z

koolexcrypto marked the issue as nullified

#5 - c4-judge

2024-05-08T12:53:59Z

koolexcrypto marked the issue as not nullified

#6 - c4-judge

2024-05-11T19:37:55Z

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