Vyper Vested Claims

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

Missing Validation for current_time > start_time in Vesting Calculation, Missing Modifier in the function, and Arithmetic Calculation error

Summary

The _calculate_vested_amount function in the smart contract assumes that current_time is always greater than or equal to start_time. This assumption can lead to unintended behavior, including potential underflow errors if current_time < start_time. Additionally, the function lacks an @internal modifier, which could expose it to unintended external calls. Furthermore, the arithmetic operations within the function would benefit from added parentheses for clarity and to ensure proper operator precedence.

Vulnerability Details

1) Assumption of current_time >= start_time:

The function calculates the elapsed time as:

elapsed: uint256 = current_time - start_time

If current_time < start_time, this subtraction will result in an underflow error in Vyper, causing the transaction to revert. This assumption is problematic because the vesting start time (start_time) might be set to a future timestamp (e.g., days or weeks after deployment). If a user calls the function before the vesting period begins, the calculation will fail.

2) Missing @internal Modifier:

The function def _calculate_vested_amount(total_amount: uint256) -> uint256: is intended to be a helper function but does not have the @internal modifier. Without this modifier, the function is treated as public by default, allowing external actors to call it directly. This exposes the contract to unnecessary risks and potential misuse.

3) Arithmetic Clarity:

The vested amount is calculated as:

vested = instant_release + (linear_vesting * elapsed) // vesting_duration

While this formula is mathematically correct, the lack of parentheses makes it less clear whether the multiplication or division should occur first. Adding parentheses improves readability and ensures the intended order of operations.

Impact

  • If current_time < start_time, the subtraction current_time - start_time will cause an underflow, reverting the transaction. This prevents legitimate users from interacting with the contract until the vesting period begins.

  • The absence of the @internal modifier allows external actors to call _calculate_vested_amount, potentially leading to misuse or gas inefficiencies.

  • The lack of parentheses in the arithmetic expression reduces code clarity, making it harder for developers to understand and maintain the code.

Tools Used

  • Manual code review.

  • Vyper compiler and runtime behavior analysis.

Recommendations

1) Add Validation for current_time:

  • Asserting current_time >= start_time is a reasonable solution to ensure that the vesting period has started before performing any calculations.

assert current_time >= start_time, "Vesting period has not started!"

2) Add the @internal Modifier:

@internal
def _calculate_vested_amount(total_amount: uint256) -> uint256:
...

3) Use Parentheses for Arithmetic Clarity:

vested = instant_release + ((linear_vesting * elapsed) // vesting_duration)
Updates

Appeal created

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

[Invalid] Underflow in `_calculate_vested_amount`

The `_calculate_vested_amount` function is called in ` claim` and `claimable_amount` functions. There is a check that ensures the `block.timestamp` is greater or equal to the `vesting_start_time` in the both functions. Also, the admin sets the start and end time of the vesting. This means it will be always correct. Therefore, there is no risk from underflow or division by zero in `_calculate_vested_amount` function.

Support

FAQs

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