HardhatDeFi
15,000 USDC
View results
Submission Details
Severity: high
Invalid

WToken Decimal Mismatch in DIVA Protocol

Summary

The AaveDIVAWrapper contract does not properly validate decimal consistency between collateral tokens and wrapped tokens (WTokens). This allows a** misconfigured or malicious DIVA pool** to use mismatched decimals, causing severe underpayments or overpayments during redemption.

Root Cause

  1. WToken Decimals are Not Verified Against Collateral Token Decimals

    • The contract assumes that the decimals of the WToken match those of the underlying collateral token, but this assumption is incorrect.

    • Example:

      • USDC (6 decimals) is used as collateral.

      • The corresponding WToken is mistakenly/maliciously set to 18 decimals.

      • This introduces a 1e12 factor difference in calculations.

  2. DIVA Pools Can Be Created with Arbitrary Decimals

    • The AaveDIVAWrapper blindly trusts DIVA pool parameters without verifying whether the decimals of the registered WToken match the original collateral.

Exploit Steps

  1. Create a DIVA Pool with a Fake WToken

    • A malicious actor deploys a custom WToken with 18 decimals, but registers it as collateral for a 6-decimal token (e.g., USDC).

    • The AaveDIVAWrapper does not check for decimal mismatches.

  2. Users Deposit Funds into the Pool

    • Users deposit USDC (6 decimals) into the pool, expecting to receive equivalent WTokens.

    • However, the conversion rate is incorrect, leading to inflated or reduced balances.

  3. Redemption Phase - Users Lose Funds

    • When users redeem their WTokens, the protocol miscalculates collateral amounts:

      • If USDC has 6 decimals, but the WToken has 18, users might get 1e12x more or less USDC.

      • Example: A user expecting 1 USDC (1e6) might receive 0.000000000001 USDC (1e-12) or 1,000,000 USDC (1e12).

    • This severely disrupts the protocol and can drain liquidity pools or cause users to lose funds.


Proof of Concept (PoC)

**Obj->**Demonstrate how a pool with mismatched decimals can cause incorrect collateral redemptions.

PoC Steps

  1. Deploy a Misconfigured/Malicious WToken

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.26;
    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    contract MaliciousWToken is ERC20 {
    constructor() ERC20("Fake WToken", "FWTK") {
    _mint(msg.sender, 1_000_000 * 1e18); // Mint 1M tokens with 18 decimals
    }
    function decimals() public pure override returns (uint8) {
    return 18; // Set to 18 decimals
    }
    }
  2. Register it as a 6-Decimal Collateral Token in AaveDIVAWrapper

    function registerFakeCollateral(address fakeToken, address realCollateral) external {
    _collateralTokenToWToken[realCollateral] = fakeToken;
    }
  3. Deposit 100 USDC into the Pool

    • Expected WToken balance (correct case): 100 WTokens

    • Actual balance (due to decimal mismatch): 100 * 1e12 WTokens (wrong amount)

  4. Redeem WTokens

    • When the user redeems their 100 WTokens, they should receive 100 USDC.

    • Instead, they receive 0.0000000001 USDC or 100,000,000,000 USDC, depending on whether the protocol divides or multiplies incorrectly.


Impact

🔴 Severity: HIGH
💰 Loss of Funds: Users may receive 1e12x too much or too little collateral.
📉 Liquidity Drain: The protocol may overpay or underpay, destabilizing liquidity pools.
⚠️ Trust Damage: Users experiencing incorrect redemptions will lose trust in the protocol.


Mitigation Strategies

Enforce Decimal Consistency Between Collateral & WToken

Before registering a collateral token, validate decimals match.

  • require(
    IERC20Metadata(_collateralToken).decimals() == IERC20Metadata(_wToken).decimals(),
    "Mismatched decimals between collateral and WToken"
    );

Require Explicit Decimals in DIVA Pool Creation

When creating a pool, verify that the collateral token decimals match the registered WToken decimals.

Use a Scaling Factor in All Calculations

  • Introduce a scaling factor to adjust for decimal mismatches.

    uint256 collateralDecimals = IERC20Metadata(_collateralToken).decimals();
    uint256 wTokenDecimals = IERC20Metadata(_wToken).decimals();
    uint256 scaleFactor = 10**(wTokenDecimals - collateralDecimals);

Updates

Lead Judging Commences

bube Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.