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

`Protocol/Owner` can stop a token holders from withdrawing their funds

Summary

Protocol/Owner can stop a particular token from redeeming using ThunderLoan::setAllowedToken and all the token holder of that token will not be able to redeem their funds.

Vulnerability Details

Let's say protocol allowed tokenA to receive then LP can deposite/redeem and users can take flashloan but the moment protocol/malicious owner decides to stop a token from receiving then there is no way for the LP to redeem their funds because ThunderLoan::redeem only lets you redeem allowed tokens. Even if you try to re-allow that tokenA then it will be completely new tokenA, not that old one. therefore no way for LP to redeem their funds.

//Here is POC

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import { Test, console } from "forge-std/Test.sol";
import { BaseTest, ThunderLoan } from "./BaseTest.t.sol";
import { AssetToken } from "../../src/protocol/AssetToken.sol";
import { MockFlashLoanReceiver } from "../mocks/MockFlashLoanReceiver.sol";
contract ThunderLoanTest is BaseTest {
uint256 constant AMOUNT = 10e18;
uint256 constant DEPOSIT_AMOUNT = AMOUNT * 100;
address liquidityProvider = address(123);
address user = address(456);
address user2 = address(789);
MockFlashLoanReceiver mockFlashLoanReceiver;
function setUp() public override {
super.setUp();
vm.prank(user);
mockFlashLoanReceiver = new MockFlashLoanReceiver(address(thunderLoan));
}
function test_owner_can_stop_token() public {
// Allowing tokenA to get deposite
vm.prank(thunderLoan.owner());
thunderLoan.setAllowedToken(tokenA, true);
AssetToken assetToken = thunderLoan.getAssetFromToken(tokenA);
//minting tokens to 2 LP (user, user2)
tokenA.mint(user, 2e18);
tokenA.mint(user2, 4e18);
//user is approving and depositing
vm.startPrank(user);
tokenA.approve(address(thunderLoan), 2e18);
thunderLoan.deposit(tokenA, 2e18);
//user2 is approving and depositing
vm.startPrank(user2);
tokenA.approve(address(thunderLoan), 4e18);
thunderLoan.deposit(tokenA, 4e18);
//Blocking a allowed to token
vm.prank(thunderLoan.owner());
thunderLoan.setAllowedToken(tokenA, false);
//user is redeeming
vm.prank(user);
thunderLoan.redeem(tokenA, assetToken.balanceOf(user));
}
}

Result

Failing tests:
Encountered 1 failing test in test/unit/MyTest.t.sol:ThunderLoanTest
[FAIL. Reason: ThunderLoan__NotAllowedToken(0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9)] testUnApprovedTokenDeposite() (gas: 1296284)

Impact

LP will lose their complete fund.

Tools Used

Manual review, Foundry

Recommendations

Implement a withdrawl method for allowing LP to redeem previously allowed tokens or give them some grace period before completely blocking token so that LP can redeem their funds.

Updates

Lead Judging Commences

0xnevi Lead Judge
over 1 year ago
0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Admin Input/call validation
0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

centralized owners can brick redemptions by unallowing a token

Support

FAQs

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