Description: The claim
function has a critical flaw in how it verifies vesting claims. It doesn't store the total amount a user is entitled to in the contract state, but instead relies on the caller to provide it each time. This allows an attacker to claim amounts multiple times by simply calling the function repeatedly with valid merkle proofs.
Lines 180-206 in the claim function:
Impact: An attacker can drain all of the vesting contract's tokens by:
Creating a valid merkle proof for a small amount (e.g., 100 tokens)
Repeatedly calling claim()
with this proof
The contract will continuously release more tokens based on the vesting schedule without tracking that these releases are for the same allocation
Each time the function is called with the same total_amount and a valid proof, it will calculate a new vested amount based on the current timestamp. The contract doesn't track that these multiple claims are for the same original allocation.
Proof of Concept: Assuming Alice has a valid proof for 1000 tokens:
At day 1 of vesting, Alice claims 310 tokens (31% instant release)
At day 100, Alice calls claim again with the same proof and receives additional tokens based on the linear vesting schedule
Alice can repeat this process, effectively claiming multiple times for the same 1000 token allocation
Recommended Mitigation: Store the total allocation for each user alongside their claimed amount:
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.