It is intended that withdraw function reverts the transaction if the CapitalPool contract does not have enough balance for the token transfer however it won't be failed even if CapitalPool does not have any token. Therefore the withdraw function will be executed succesfuly althought it is supposed to fail.
As It is shown below withdraw function uses the _safe_transfer_from() method in order to send ERC20 tokens from CapitalPool to TokenManager contract.
The _safe_transfer_from method of Rescuable.sol() will do following low level call (bool success, ) = token.call( abi.encodeWithSelector(TRANSFER_FROM_SELECTOR, from, to, amount) )
where TRANSFER_FROM_SELECTOR is bytes4 private constant TRANSFER_FROM_SELECTOR = bytes4(keccak256(bytes("transferFrom(address,address,uint256)")))
and check if it's return value false however the low level call function won't be reverted if CapitalPool has not enough funds to send. This issue can be reproduced by following test method :
Since low level transfer calls used in TokenManager::tillIn() as well ,TokenManager contract can work unintendedly and this may affect overall contract logic.
Manual analysis and Foundry
The problem can be fixed as implementing following dependencies to TokenManager.sol : SafeERC20 library of OpenZeppelin and ERC20 interface then changing this line to IERC20(_tokenAddress).safeTransferFrom(capitalPoolAddr, _msgSender(), claimAbleAmount)
. Additionaly changing all the low level transfer and transferFrom function calls with safeTransfer and safeTransferFrom would be better because the low level calls don't revert on failure if call isn't failed because of unsufficient gas or called function's revert.In case the called function does not exist or it simply returns a value,low level call returns true.Therefore in such situations following code snippets from Rescuable.sol won't revert even if transferFrom or transfer function does not work correctly.
I believe the issues and duplicates do not warrant low severity severity as even if the call to transfers returns false instead of reverting, there is no impact as it is arguably correct given there will be insufficient funds to perform a rescue/withdrawal. This will not affect `tillIn()` as there are explicit balance [checks that revert accordingly](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/core/TokenManager.sol#L255-L260) to prevent allowing creation of offers without posting the necessary collateral
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.