Vyper Vested Claims

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

[L-4] Block timestamp can be manipulated by miners to mess with the vested computation

Summary

The block timestamp can be influenced by miners to a certain degree. And it is used inside the `VestedAirdrop` contract to define if we have reached TGE or the end of the vesting period.

Vulnerability Details

VestedAirdrop::_calculate_vested_amount, VestedAirdrop::claimable_amount, and VestedAirdrop::claim use the block timestamp to calculate the vested and claimable amounts. This could be manipulated by miners to negatively affect the contract.

Impact

The impact should be minimal since the period between TGE and the end of the vesting period is likely long enough to prevent miners from significantly manipulating the timestamp. However, it remains a risk to consider.

Proof of Concept:

def test_audit_claim_timestamp_manipulation(self):
"""Test realistic timestamp manipulation within Ethereum constraints"""
initial_amount = to_wei_ether(1000)
total_time = 90 * ONE_DAY # 90 days vesting period
# Setup initial state
start_time = block_timestamp()
# Calculate expected initial vested amount (31% instant)
expected_initial = (initial_amount * 31) // 100
# Try to manipulate timestamp by maximum allowed (15 seconds)
MAX_TIMESTAMP_MANIPULATION = 15 # seconds
# Simulate multiple blocks with maximum timestamp manipulation
for _ in range(10): # Simulate 10 blocks of manipulation
# Move time forward by max allowed
boa.env.time_travel(MAX_TIMESTAMP_MANIPULATION)
# Calculate manipulated amount
manipulated_time = block_timestamp() - start_time
linear_portion = (initial_amount * 69) // 100
expected_manipulated = expected_initial + (linear_portion * manipulated_time) // total_time
# Verify the manipulation effect
actual_vested = self.airdrop.claimable_amount(self.user1, initial_amount)
assert actual_vested == expected_manipulated, "Manipulation should follow linear vesting schedule"
# Try to claim with manipulated timestamp
if actual_vested > 0:
with boa.reverts("Invalid proof"): # Should fail due to invalid merkle proof
self.airdrop.claim(self.user1, initial_amount, [b"0x00"])
# Calculate total manipulation effect
total_manipulation = MAX_TIMESTAMP_MANIPULATION * 10 # 150 seconds total
manipulation_percentage = (total_manipulation / total_time) * 100
print(f"Total time manipulated: {total_manipulation} seconds")
print(f"Percentage of vesting affected: {manipulation_percentage:.4f}%")
# Assert the manipulation impact is minimal
assert manipulation_percentage < 0.01, "Timestamp manipulation should have minimal impact"

Recommendations

Consider adding a delay if you intend to use timestamps in the contract (e.g., 15 seconds). Alternatively, use block numbers instead of timestamps to calculate the time passed, though this could be more complex. Another option is to use an oracle to obtain the timestamp.

Updates

Appeal created

bube Lead Judge 4 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.