Skip to main content
A multi-token vesting contract for linear vesting schedules with optional cliffs.

Overview

MultiTokenVesting is a Solidity contract for linear vesting of several ERC-20 tokens from a single deployment. An Owner creates vesting schedules for beneficiaries, and beneficiaries claim vested tokens over time. Vesting is linear, with an optional cliff. The Owner can revoke a schedule.

Key features

Multi-token support

One contract handles vesting schedules for many ERC-20 tokens (USDC, WETH, UNI), without a deployment per token.

Revocable schedules

When the Owner revokes a schedule, the vested amount stays claimable by the beneficiary and the unvested part goes back to the Owner.

Gas optimization

Gas cost is kept down by:
  • Packed data structures (addresses and flags)
  • Custom errors instead of revert strings
  • Claiming directly by schedule index

Safety features

  • Solvency check: the tokens a schedule needs are transferred into the contract when the schedule is created.
  • Withdraw excess: the Owner can only withdraw tokens sent to the contract by accident, not tokens locked in active schedules.

Supported tokens

The contract handles ERC-20 tokens only.
Native gas tokens, PEAQ included, are not supported. Wrap them into an ERC-20 representation first.

Vesting logic

Vesting follows a simple timeline:
  • Before cliff: 0 claimable
  • After cliff → end: linear unlock
  • After end: 100% claimable
Formula: VestedAmount = (TotalAmount * (CurrentTime - StartTime)) / Duration Example:
  • Total amount: 1000
  • Duration: 1000 seconds
  • Cliff: 250 seconds
Progression:
  • At 0s: 0 vested
  • At 250s: 250 vested
  • At 500s: 500 vested
  • At 1000s: 1000 vested

Deploy on peaq

You deploy MultiTokenVesting on peaq EVM like any other Solidity contract: With Foundry:

How to use

A) Approve tokens (ERC-20)

Approve the vesting contract to pull tokens from the Owner’s wallet. This call goes to the ERC-20 token contract, not to the vesting contract.

B) Create vesting schedule (Owner-only)

Create a schedule that starts now, has a 30-day cliff, and vests linearly over 1 year.

C) Claim (Beneficiary-only)

Beneficiaries claim by scheduleIndex:
The scheduleIndex is emitted by the ScheduleCreated event. Index that event in your app and store the schedule indices per beneficiary.

D) Revoke (Owner-only)

The Owner can revoke a schedule:
On revoke, the beneficiary keeps the amount vested up to the revoke time and the rest returns to the Owner.

E) Withdraw excess (Owner-only)

Withdraw tokens that are not locked in active schedules:

API reference

VestingSchedule fields

  • beneficiary (address)
  • start (uint64)
  • revoked (bool)
  • claimed (bool)
  • token (address)
  • duration (uint64)
  • cliff (uint64)
  • totalAmount (uint256)
  • amountClaimed (uint256)

Errors

Security notes

  • Solidity ^0.8.20 includes overflow checks by default.
  • SafeERC20 handles non-standard ERC-20 implementations.
  • Claim flows should follow Checks-Effects-Interactions.
  • Centralization risk: the Owner can revoke schedules, so beneficiaries have to trust the Owner.