Vyper Vested Claims

First Flight #34
Beginner FriendlyDeFi
100 EXP
View results
Submission Details
Severity: low
Invalid

Owner Can Withdraw Unvested Tokens via rescue_tokens

Summary

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.

Vulnerability Details

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.

@external
def rescue_tokens(to: address, amount: uint256):
self.onlyOwner()
log TokensRescued(to, amount)
_success: bool = extcall IERC20(self.token).transfer(to, amount)
assert _success, "Transfer failed"

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.

Impact

  • 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.

Tools Used

Manual code review

Recommendations

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:

  1. Check Unallocated Balance: Modify rescue_tokens to ensure it only allows withdrawing tokens that exceed the sum of vested and unvested user entitlements.

  2. Use a Separate Treasury: Instead of holding all vested tokens in the contract, transfer only the vested portions to users periodically to minimize risk.

  3. 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.

Updates

Appeal created

bube Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

[Invalid] Owner can call rescue_tokens and withdraw users tokens

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

Support

FAQs

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