Vyper Vested Claims

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

Missing Zero-Address Checks

Summary

The token vesting contract lacks validation to ensure that critical address parameters, particularly the token address, are not set to the zero address.
This omission creates a risk that tokens could be sent to an unrecoverable address if the contract is misconfigured during deployment, potentially resulting in permanent loss of funds.

Vulnerability Details

The constructor accepts the token address without performing any validation:

@deploy
def __init__(merkle_root: bytes32, token: address, vesting_start_time: uint256, vesting_end_time: uint256):
"""
@notice Initialize the contract with the merkle root, token address, vesting start and end time
@param merkle_root: bytes32, the merkle root of the vesting list
@param token: address, the address of the token contract
@param vesting_start_time: uint256, the start time of the vesting
@param vesting_end_time: uint256, the end time of the vesting
"""
self.merkle_root = merkle_root
self.token = token
self.vesting_start_time = vesting_start_time
self.vesting_end_time = vesting_end_time
self.owner = msg.sender
log MerkleRootUpdated(merkle_root)

If token is accidentally set to the zero address, any subsequent token transfers would be directed to this address, and those tokens would be permanently lost as no one controls the private key for the zero address.

Impact

The impact of this vulnerability includes:

  1. Permanent Token Loss: If the contract is deployed with the token address set to the zero address, all tokens distributed through the contract would be permanently lost.

  2. Deployment Failure Necessity: If the issue is discovered after deployment, a complete redeployment would be necessary, potentially disrupting the vesting schedule and requiring coordination with all stakeholders.

  3. Trust Erosion: A configuration error of this nature could erode user trust in the project's technical competence.

  4. Administrative Overhead: Rectifying the issue would require significant administrative effort to generate new Merkle proofs and communicate changes to users.

Tools Used

Manual Review

Recommendations

Implement zero-address validation in the constructor:

@deploy
def __init__(merkle_root: bytes32, token: address, vesting_start_time: uint256, vesting_end_time: uint256):
"""
@notice Initialize the contract with the merkle root, token address, vesting start and end time
@param merkle_root: bytes32, the merkle root of the vesting list
@param token: address, the address of the token contract
@param vesting_start_time: uint256, the start time of the vesting
@param vesting_end_time: uint256, the end time of the vesting
"""
assert token != empty(address), "Token address cannot be zero"
assert vesting_start_time < vesting_end_time, "Invalid vesting period"
assert vesting_start_time > 0, "Vesting start time must be greater than zero"
self.merkle_root = merkle_root
self.token = token
self.vesting_start_time = vesting_start_time
self.vesting_end_time = vesting_end_time
self.owner = msg.sender
log MerkleRootUpdated(merkle_root)

Additionally, similar validations should be added to other functions that accept address parameters:

@external
def rescue_tokens(to: address, amount: uint256):
"""
@notice This function is used to rescue tokens from the contract
@param to address, the address to send the tokens to
@param amount uint256, the amount of tokens to send
@dev this is a "better safe then sorry" function, use it only in case of emergency
@dev This function can only be called by the owner
"""
self.onlyOwner()
assert to != empty(address), "Recipient address cannot be zero"
assert amount > 0, "Amount must be greater than zero"
log TokensRescued(to, amount)
_success: bool = extcall IERC20(self.token).transfer(to, amount)
assert _success, "Transfer failed"
Updates

Appeal created

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

Support

FAQs

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