Create a simple linear ERC-20 token vesting contract, test it with Foundry, and generate a vesting schedule CSV using Python.
This repository is designed to be useful for:
- startup token vesting
- team allocation vesting
- advisor vesting
- community or treasury token release planning
Supported platforms:
- macOS / Linux
- Windows with WSL 2
- Solidity token vesting contract
- Foundry test suite
- Python vesting schedule generator
- GitHub Actions CI
Makefilefor local DevOps workflow.env.examplefor deployment configuration
The contract supports:
- one ERC-20 token
- one beneficiary
- one linear vesting schedule
- partial release after vesting starts
- final release after vesting ends
Useful view functions:
vestedAmount(timestamp)releasableAt(timestamp)releasable()remainingAllocation()fundingShortfall()
- Open repo on GitHub.
- Click
Code->Download ZIP. - Extract ZIP.
- Open terminal in extracted folder.
- Run:
chmod +x easy_start.sh
./easy_start.shWhat this does automatically:
- checks required tools
- checks Solidity formatting
- runs Solidity lint checks
- builds contracts
- runs Foundry tests
- validates Python script
- creates sample output file
Sample output file:
output/sample-vesting-schedule.csv
CSV columns:
steptimestamp_utcelapsed_daysvested_amount_weivested_percent
cp .env.example .env
make ci-localUse WSL 2, then run the same Linux commands inside WSL.
- Foundry
- Python
3.10+ make
Install Foundry:
curl -L https://foundry.paradigm.xyz | bash
foundryupFormat:
make fmtLint:
make lintBuild:
make buildTest:
make testValidate Python:
make pycheckGenerate vesting schedule CSV:
make scheduleRun full local CI flow:
make ci-localGenerate your own schedule file:
python3 scripts/vesting_schedule.py \
--total-allocation 1000000000000000000000 \
--start-date 2026-03-01 \
--duration-days 365 \
--interval-days 30 \
--output output/vesting-schedule.csvExample:
- total allocation =
1000tokens with18decimals - vesting start date =
2026-03-01 - vesting duration =
365days - one row every
30days
Copy .env.example to .env:
cp .env.example .envSet these values:
RPC_URL=https://your-rpc-endpoint
PRIVATE_KEY=your_private_key_without_0x
TOKEN_ADDRESS=0xYourTokenAddress
BENEFICIARY_ADDRESS=0xYourBeneficiaryAddress
START_TIMESTAMP=1772323200
DURATION_SECONDS=31536000
TOTAL_ALLOCATION_WEI=1000000000000000000000What these mean:
RPC_URL: blockchain RPC endpointPRIVATE_KEY: deployer wallet private key without0xTOKEN_ADDRESS: ERC-20 token contract addressBENEFICIARY_ADDRESS: receiver of vested tokensSTART_TIMESTAMP: vesting start in Unix timestampDURATION_SECONDS: total vesting durationTOTAL_ALLOCATION_WEI: total token amount in smallest unit
If .env is filled correctly:
chmod +x deploy.sh
./deploy.shOr pass values directly:
./deploy.sh \
0xTokenAddress \
0xBeneficiaryAddress \
1772323200 \
31536000 \
1000000000000000000000src/
LinearTokenVesting.sol
MockERC20.sol
test/
LinearTokenVesting.t.sol
scripts/
vesting_schedule.py
.github/workflows/
ci.yml
.env.example
deploy.sh
easy_start.sh
foundry.toml
Makefile
requirements.txt
README.md
GitHub Actions automatically runs:
forge fmt --checkforge lintforge buildforge test --force -vvpython3 -m py_compile scripts/*.py- sample schedule generation
- This project does not deploy automatically by itself.
- You must fund the vesting contract with tokens before
release()can work. - If the contract balance is lower than remaining vested tokens,
fundingShortfall()shows the missing amount. - Never commit
.env.
- audit before production use
- verify constructor values carefully
- protect deployer private keys
- test on testnet before mainnet
MIT. See LICENSE.