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

Griefing Attack via Fake WToken Registrations

Summary

This griefing attack exploits the lack of validation in token registration, allowing an attacker to trap user deposits in a fake token. By validating token authenticity, enforcing ERC20 compliance, and implementing a whitelist, the protocol can eliminate this risk and prevent future fund loss.

The AaveDIVAWrapper contract lacks proper validation of token authenticity during collateral token registration, allowing an attacker to frontrun legitimate registrations with a fake WToken. This can result in users unknowingly depositing funds into an invalid or malicious token contract, leading to permanently stuck assets.


Root Cause

  1. No Validation of Token Authenticity

    • The function registerCollateralToken does not verify whether the provided token is a valid ERC20 or even deployed on the correct chain.

    • Ex

      • An attacker frontruns a legitimate collateral token registration by submitting a fake WToken with the same address but on another chain.

      • Users deposit funds into this fake token, but it does not map to any real collateral.

  2. No On-Chain Existence Check

    • The contract blindly trusts the input address, without verifying:

      • If the token exists on the current chain.

      • If the token implements ERC20 functions properly.


Attack Scenario

Exploit Steps

  1. Attacker Deploys a Fake WToken

    • A fake token contract is deployed that imitates a real collateral token.

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.26;
    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    contract FakeWToken is ERC20 {
    constructor() ERC20("Fake WToken", "FWTK") {
    _mint(msg.sender, 1_000_000 * 1e18);
    }
    }
  2. Attacker Frontruns registerCollateralToken

    • Before a legitimate user registers real collateral (e.g., USDC), the attacker registers the fake token with the same address as the real token from another chain.

    function frontRunCollateralRegistration(AaveDIVAWrapper wrapper, address fakeToken) external {
    wrapper.registerCollateralToken(fakeToken);
    }
  3. Users Deposit into the Fake Token

    • Users think they are interacting with genuine collateral, but their funds go into the attacker's fake WToken.

  4. Funds Get Stuck

    • The fake WToken does not map to a real collateral token.

    • Users cannot withdraw or redeem their deposits, effectively locking all funds permanently.


Impact

💰 Loss of Funds: Deposited assets are stuck in an invalid WToken.
⚠️ Trust Erosion: Users lose confidence in the protocol after losing assets.
Protocol Downtime: Requires an urgent fix to revoke fake WToken registrations.


Proof of Concept (PoC)

Objective-> Demonstrate how an attacker can frontrun token registration and trap user funds.

PoC Steps

  1. Deploy the Fake WToken

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.26;
    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    contract FakeWToken is ERC20 {
    constructor() ERC20("Fake WToken", "FWTK") {
    _mint(msg.sender, 1_000_000 * 1e18);
    }
    }
  2. Register Fake Token as Collateral

    function registerFakeCollateral(address fakeToken, AaveDIVAWrapper wrapper) external {
    wrapper.registerCollateralToken(fakeToken);
    }
  3. Users Deposit Funds into Fake Token

    • They assume it's real but cannot withdraw later.


Mitigation Strategies

Verify Token Authenticity Before Registration

  • Check for Contract Code

    function isValidToken(address token) internal view returns (bool) {
    uint256 size;
    assembly {
    size := extcodesize(token)
    }
    return size > 0;
    }
  • Enforce ERC20 Compliance

    function isERC20(address token) internal view returns (bool) {
    try IERC20Metadata(token).totalSupply() returns (uint256) {
    return true;
    } catch {
    return false;
    }
    }

Use a Whitelist for Known Collateral Tokens

  • Only allow pre-approved tokens for registration.

    mapping(address => bool) private _approvedCollateralTokens;
    function addApprovedCollateralToken(address _token) external onlyOwner {
    require(isValidToken(_token), "Invalid token");
    require(isERC20(_token), "Not ERC20");
    _approvedCollateralTokens[_token] = true;
    }
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.