Beginner FriendlyFoundryDeFiOracle
100 EXP
View results
Submission Details
Severity: high
Valid

Unable to withdraw all underlying tokens

Summary

When attempting to withdraw all underlying tokens by calling the "redeem" function with the maximum uint256 value, the liquidity provider receives a balance exceeded error. This occurs because, after the deposit, the exchange rate increases, and the calculated quantity of underlying tokens, based on the exchange rate, exceeds the quantity of existing tokens in the balance.

PoC

This test demonstrates how a liquidity provider makes a deposit and then attempts to withdraw it but receives an error:
Test:
///solidity
function testDepositCannotRedeemAllUnderlying() public setAllowedToken {
uint256 a = 1;
tokenA.mint(liquidityProvider, 100e18);
AssetToken asset = thunderLoan.getAssetFromToken(tokenA);

    vm.startPrank(liquidityProvider);
    tokenA.approve(address(thunderLoan), 100e18);
    console.log("Balance of addres this in token A", tokenA.balanceOf(address(asset)));
    console.log("Balance of liquidityProvider in AssetToken", asset.balanceOf(liquidityProvider));
    
    thunderLoan.deposit(tokenA, 10e18);
    console.log("Balance of addres this in token A", tokenA.balanceOf(address(asset)));
    console.log("Balance of liquidityProvider in AssetToken", asset.balanceOf(liquidityProvider));

    thunderLoan.redeem(tokenA, type(uint256).max);
    vm.stopPrank();

    console.log("Balance of addres this in token A", tokenA.balanceOf(address(asset)));
    console.log("Balance of liquidityProvider in AssetToken", asset.balanceOf(liquidityProvider));
    
    assertEq(a, 1);
}

}
///

Error:
[FAIL. Reason: ERC20: transfer amount exceeds balance] testDepositCannotRedeemAllUnderlying()
Logs:
Balance of addres this in token A 0
Balance of liquidityProvider in AssetToken 0
Balance of addres this in token A 10000000000000000000
Balance of liquidityProvider in AssetToken 10000000000000000000

Impact

The consequence of this error is the inability to withdraw all tokens. However, a dishonest liquidity provider can exchange only a portion of AssetTokens and later exchange the remaining when the balance of subordinate tokens increases. In other words, they exploit the vulnerability to take what does not belong to them.

Tools Used

Manual rewiev, forge tests.

Recommendations

It is recommended to prevent liquidity providers from affecting the exchange rate by removing these lines of code in the "deposit" function:
///solidity
uint256 calculatedFee = getCalculatedFee(token, amount);
assetToken.updateExchangeRate(calculatedFee);
///

Updates

Lead Judging Commences

0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

can't redeem because of the update exchange rate

Support

FAQs

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