DYAD - Shubham'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: 59/183

Findings: 1

Award: $200.84

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

Awards

200.8376 USDC - $200.84

Labels

bug
3 (High Risk)
satisfactory
sufficient quality report
:robot:_11_group
duplicate-1097

External Links

Lines of code

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

Vulnerability details

According to docs: "If a Note’s collateral value in USD drops below 150% of its DYAD minted balance, it faces liquidation. The liquidator burns a quantity of DYAD equal to the target Note’s DYAD minted balance, ..."

This means that the liquidator must have atleast the same amount or higher token balance than the user they are going to liquidate if the user's collateral ratio drops down. If the liquidator does not hold the equivalent amount of tokens, the function would revert due to underflow. Thus it would be not be possible for liquidators to liquidate if the user has high amount of dyad tokens minted.

Proof of Concept

The dyad.burn makes an external call to reduce the minted dyad balance for a particular nft.

File: VaultManagerV2.sol

  function liquidate(
    uint id,
    uint to
  ) 
    external 
      isValidDNft(id)
      isValidDNft(to)
    {
      uint cr = collatRatio(id);
      if (cr >= MIN_COLLATERIZATION_RATIO) revert CrTooHigh();
      dyad.burn(id, msg.sender, dyad.mintedDyad(address(this), id));   @> issue

   ...

The burn() makes an external call to the erc20 contract _burn() to reduce the balance of the user who called the liquidate() in this case.

File: Dyad.sol

  function burn(
      uint    id, 
      address from,
      uint    amount
  ) external 
      licensedVaultManager 
    {
      _burn(from, amount);
      mintedDyad[msg.sender][id] -= amount;
  }

Here, when deducting the amount from the balance of the liquidator, the function will throw error due to underflow if the liquidator's balance is less than the user it is about to liquidate.

File: ERC20.sol

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;            @> error when reducing the liquidator's balance

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }

Thus for a liquidator to liquidate a user, first they must have that particular or higher number of dyad that they are going to liquidate for which they must have initially deposited collateral at the required ratio to be able to mint dyad themselves. Given that the rewards can be transferred to another nft id & there isn't a specific 'liquidator' role assigned by the protocol meaning anyone can be a liquidator, the liquidator must first put in their own funds to be one.

In the case where top users holding high volumes of dyad gets their collateral ratio below 150%, they won't get liquidated because the liquidator does not have enough token balance themselves. Even if the liquidators manage to get the required balance to liquidate at a later time, the user could have added extra collateral & prevent themselves from being liquidated.

Tools Used

Manual Review

Burn the nft owner's token balance instead of burning the liquidator's.

Assessed type

Invalid Validation

#0 - c4-pre-sort

2024-04-29T05:52:15Z

JustDravee marked the issue as duplicate of #1097

#1 - c4-pre-sort

2024-04-29T08:34:39Z

JustDravee marked the issue as sufficient quality report

#2 - c4-judge

2024-05-11T12:21:59Z

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