Auric

TokenVesting

src/TokenVesting.sol — locks any ERC-20 and releases it linearly to a fixed beneficiary.

Constructor

constructor(address _token, address _beneficiary, uint64 _cliffDuration, uint64 _duration)
ParameterDescription
_tokenERC-20 to vest (typically AUR)
_beneficiaryImmutable recipient of released tokens
_cliffDurationSeconds from deployment until the cliff
_durationTotal vesting duration in seconds (>= _cliffDuration)

Timestamps are anchored to block.timestamp at deploy:

State varValue
startblock.timestamp
cliffstart + _cliffDuration
endstart + _duration

Reverts with InvalidDuration() if _duration == 0 or _cliffDuration > _duration.

Deposit

function deposit(uint256 amount) external

One-time, one-way. Transfers amount tokens from msg.sender into the contract. Subsequent calls revert with AlreadyDeposited(). Reverts with ZeroAmount() if amount == 0.

Caller must approve this contract before calling.

Vesting Schedule

function vestedAmount(uint64 timestamp) public view returns (uint256)
Time rangeReturns
timestamp < cliff0
cliff <= timestamp < endtotalAmount * (timestamp - start) / (end - start)
timestamp >= endtotalAmount

Accrual is linear from start, not from cliff. The cliff makes the entire accrued amount claimable in a lump sum on first release.

Example: 1,000 tokens, 30-day cliff, 365-day total. At day 30, (1000 * 30) / 365 ≈ 82 tokens are immediately claimable.

Release

function release() external

Transfers all currently releasable tokens to beneficiary. Anyone can call; tokens always go to the fixed beneficiary, never to msg.sender.

CheckError
block.timestamp < cliffCliffNotReached()
releasable() == 0NothingToRelease()

State

VariableTypeDescription
totalAmountuint256Set by deposit
releaseduint256Cumulative tokens already transferred
depositedboolGuards against double-deposit

Events

EventEmitted by
Deposited(address depositor, uint256 amount)deposit
Released(address beneficiary, uint256 amount)release

Custom Errors

ErrorCondition
AlreadyDeposited()Second call to deposit
ZeroAmount()deposit(0)
InvalidDuration()_duration == 0 or _cliffDuration > _duration
CliffNotReached()release called before cliff
NothingToRelease()No vested tokens pending release