The rescue_tokens function allows the contract owner to withdraw any amount of tokens from the contract, including unvested tokens meant for users. This introduces a critical risk where the owner could drain funds that should be progressively distributed to users.
The contract includes a function rescue_tokens, which allows the owner to transfer tokens to any address in case of an emergency. However, there is no restriction preventing the owner from withdrawing unvested tokens that are intended for users. Since the contract itself holds the tokens for vesting, an owner with malicious intent (or a compromised private key) could effectively steal funds before they are claimed by rightful recipients.
There is no safeguard ensuring that only excess tokens can be withdrawn. This means that even if tokens are committed to users via the vesting schedule, the owner could remove them at will.
Users may not receive their allocated tokens if the owner withdraws them early.
Even if the owner is trusted, a compromised private key could result in all unvested funds being stolen.
Trust in the contract's fairness and security is compromised.
Manual code review
To prevent this exploit, restrict the rescue_tokens function to only allow withdrawals of excess tokens that are not part of the vesting schedule. A possible solution:
Check Unallocated Balance: Modify rescue_tokens
to ensure it only allows withdrawing tokens that exceed the sum of vested and unvested user entitlements.
Use a Separate Treasury: Instead of holding all vested tokens in the contract, transfer only the vested portions to users periodically to minimize risk.
Introduce a Timelock: If rescue_tokens
is necessary, implement a time delay before execution to allow users to react if an unauthorized withdrawal is detected.
The `owner` is trusted and the function `rescue_tokens` can be called only by the owner and only in case of emergency. This means the owner will not act maliciously and will not call the function without need. Also, issues realated to the malicious admin actions are invalid according to the CodeHawks documentation: https://support.cyfrin.io/en/articles/10059196-findings-validity
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.