Updating the Merkle root via set_merkle_root does not reset or adjust the claimed_amount mapping. This misalignment between the new user allocations (as defined by the updated root) and the historical claimed amounts can lead to users being able to claim additional tokens beyond their intended allocation.
The set_merkle_root function allows the contract owner to change the Merkle root at any time:
However, when this update occurs, the contract does not modify the claimed_amount mapping that tracks the cumulative tokens claimed by each user. If the new Merkle tree defines different per-user allocations than the previous one, the already claimed amounts remain based on the old allocations. This discrepancy can be exploited if the new total allocation for a user is higher than before, allowing the user to claim additional tokens computed as:
claimable = new_vested_amount (from new total_amount) - previously_claimed_amount
Overclaiming Risk: Users may be able to claim more tokens than originally allocated. For example, if a user's allocation is increased in the new Merkle tree while their claimed_amount remains unchanged, they can claim the difference, effectively receiving extra tokens.
Vesting Schedule Disruption: The vesting logic becomes inconsistent as the claimed_amount no longer aligns with the allocations defined by the current Merkle root.
Centralization Abuse: A malicious owner could intentionally update the Merkle root to inflate user allocations and, if colluding with a beneficiary, allow them to claim an excessive number of tokens.
Scenario Example:
UserA is allocated 1,000 tokens in the initial Merkle tree and claims 310 tokens (31% TGE). Later, the owner updates the Merkle root to reflect a new allocation of 2,000 tokens for UserA without resetting claimed_amount. The contract now computes:
Over time, as vested increases according to the new schedule, UserA can claim more tokens than originally intended.
N/A
When updating the Merkle root, either:
- Disallow updates once claims have begun, or
- Reset the claimed_amount mapping to zero (or adjust it in line with the new allocations) to ensure consistency between historical claims and the new Merkle tree.
If the contract is reused with another Merkle root and there is a user participated in the previous airdrop, user's claimed amount will not be set to 0. This means if the new total amount is 1000 and the user has claimed amount (from previous aidrop) equals to 500, the user will be able to receive only 500 tokens instead of intended 1000. The `set_merkle_root` is called only by the owner who is trusted. Therefore, we can assume that the owner will not call the function during the existing vesting period or before all users claim their token amounts. The owner can check manually if all users have claimed their tokens.
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.