The TokenManager
contract has an issue in the withdraw
function, which fails due to the CapitalPool
contract not granting approval to the TokenManager
contract for token transfers. As a result, the _safe_transfer_from
function will revert, locking users' funds permanently within the contract.
In the TokenManager
contract's withdraw
function, the following code attempts to transfer ERC20 tokens from the CapitalPool
to the caller:
However, this function relies on CapitalPool
having given the necessary approval for TokenManager
to perform the transfer. Since the CapitalPool
contract's approve function isn't invoked before this transfer attempt, the approval is not granted, leading to the following _safe_transfer_from
function call reverting:
_safe_transfer_from
function:
The following PoC demonstrates this issue. Note that I made changes to PreMarkets.sol to facilitate testing:
I modified the createOffer
function to return the stock and offer addresses, which will be used for closing the offer in order to be able to withdraw the deposited amount. This change was made because working with events in Foundry is cumbersome. The updated function is as follows:
CMD to run the test forge test --mt test_PermanentDoS --via-ir -vv
Users will not be able to withdraw their funds as the _safe_transfer_from
function will revert due to the lack of approval. This issue effectively permanently locks users' funds in the contract.
VSCode, Foundry
To resolve the issue, ensure that the CapitalPool
contract grants approval to the TokenManager
contract before attempting to perform the token transfer.
Here's the diff showing the needed change:
This issue's severity has similar reasonings to #252, whereby If we consider the correct permissioned implementation for the `approve()` function within `CapitalPool.sol`, this would be a critical severity issue, because the withdrawal of funds will be permanently blocked and must be rescued by the admin via the `Rescuable.sol` contract, given it will always revert [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/core/CapitalPool.sol#L36-L38) when attempting to call a non-existent function selector `approve` within the TokenManager contract. Similarly, the argument here is the approval function `approve` was made permisionless, so if somebody beforehand calls approval for the TokenManager for the required token, the transfer will infact not revert when a withdrawal is invoked. I will leave open for escalation discussions, but based on my first point, I believe high severity is appropriate. It also has a slightly different root cause and fix whereby an explicit approval needs to be provided before a call to `_safe_transfer_from()`, if not, the alternative `_transfer()` function should be used to provide an approval, assuming a fix was implemented for issue #252
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.