The low level transfer function in TokenManager::withdraw()
can lead to failed withdrawals if the caller is a contract (for example Gnosis wallet or a smart contract wallet).
The TokenManager
contract allows users to withdraw their deposited tokens. In case the withdrawn token is a wrapped form of the native token, the withdraw()
function sends the ETH using the low-level transfer()
function (line 169):
The transfer()
only forwards 2300 gas, which is not enough for the recipient to execute any non-trivial logic in a receive()
or fallback function.
And because only the depositor address can withdraw the locked tokens, this can lead to the deposited tokens being locked forever if the depositor is a smart contract instead of EOA.
In case the withdrawn token is wrapped native token, if a user callsTokenManager::withdraw()
from a contract account like a multisig or smart contract wallet that has a receive()
function requiring >2300 gas, the withdraw call will fail permanently.
The withdrawn ETH will be locked forever, leading to loss of funds.
Manual review.
Use call()
instead of transfer()
to send ETH in claim()
:
This forwards all available gas and allows contract recipients to execute arbitrary logic.
Invalid, known issues [Medium-2](https://github.com/Cyfrin/2024-08-tadle/issues/1)
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.