Skip to main content

Overview

A comprehensive token project template with four production-grade contracts covering the full token lifecycle: creation, distribution via vesting, yield via staking, and secure management via multisig.
DifficultyIntermediate
CategoryToken
ChainsEthereum
ServicesNone
LicenseApache-2.0

Quick Start

dokrypt init my-token --template evm-token
cd my-token
dokrypt up

Generated Files

my-token
dokrypt.yaml
foundry.toml
README.md
contracts
token
ManagedToken.sol
vesting
VestingSchedule.sol
staking
StakeRewards.sol
multisig
MultiSig.sol
test
token
ManagedToken.t.sol
vesting
VestingSchedule.t.sol
staking
StakeRewards.t.sol
multisig
MultiSig.t.sol
scripts
deploy-token.js
setup-vesting.js

Contracts

ManagedToken.sol

Full-featured ERC-20 with owner-controlled minting, burning, and emergency pause. Constructor:
constructor(string memory name, string memory symbol, uint256 initialSupply)
Functions:
FunctionAccessDescription
transfer(to, amount)PublicTransfer tokens (reverts when paused)
approve(spender, amount)PublicApprove spending
transferFrom(from, to, amount)PublicTransfer on behalf
mint(to, amount)OwnerMint new tokens
burn(amount)PublicBurn your own tokens
pause()OwnerPause all transfers
unpause()OwnerResume transfers
transferOwnership(newOwner)OwnerTransfer ownership
Events: Transfer, Approval, Paused, Unpaused, OwnershipTransferred

VestingSchedule.sol

Linear token vesting with configurable cliff and duration. Constructor:
constructor(address _token)
Schedule struct:
struct Schedule {
    address beneficiary;   // Recipient
    uint256 totalAmount;   // Total tokens to vest
    uint256 released;      // Tokens already released
    uint256 start;         // Vesting start timestamp
    uint256 cliff;         // Cliff end timestamp
    uint256 duration;      // Total duration (seconds)
    bool revoked;          // Cancellation status
}
Functions:
FunctionAccessDescription
createSchedule(beneficiary, amount, start, cliffDuration, duration)OwnerCreate vesting schedule
release(scheduleId)PublicRelease vested tokens to beneficiary
revoke(scheduleId)OwnerCancel schedule, return unvested tokens
releasableAmount(scheduleId)ViewCalculate currently vested amount
Vesting Logic:
  • Before cliff: 0 tokens are vested
  • After cliff: tokens vest linearly over the remaining duration
  • Formula: vestedAmount = totalAmount * (currentTime - start) / duration
Events: ScheduleCreated, TokensReleased, ScheduleRevoked
Use dokrypt chain time-travel to test vesting schedules without waiting. For example, dokrypt chain time-travel 180d jumps past a 6-month cliff.

StakeRewards.sol

Synthetix-style proportional staking rewards. Users stake tokens and earn rewards proportional to their share of the total stake. Constructor:
constructor(address _stakingToken, address _rewardsToken)
Functions:
FunctionAccessDescription
stake(amount)PublicStake tokens
withdraw(amount)PublicUnstake tokens
getReward() / claimReward()PublicClaim accumulated rewards
exit()PublicWithdraw all + claim rewards
setRewardsDuration(duration)OwnerSet reward period length
notifyRewardAmount(amount)OwnerStart/refill reward distribution
earned(account)ViewCheck pending rewards
rewardPerToken()ViewCurrent reward per staked token
Reward Calculation:
  • rewardRate = rewardAmount / duration
  • rewardPerToken += rewardRate * timeDelta / totalStaked
  • earned = stakedBalance * (rewardPerToken - userPaidPerToken) + storedRewards
Events: Staked, Withdrawn, RewardPaid, RewardsDurationUpdated

MultiSig.sol

M-of-N multisignature wallet for secure fund management. Constructor:
constructor(address[] memory _owners, uint256 _required)
  • _owners: Array of owner addresses
  • _required: Minimum confirmations needed to execute
Transaction struct:
struct Transaction {
    address to;           // Target address
    uint256 value;        // ETH value
    bytes data;           // Calldata
    bool executed;        // Execution status
    uint256 confirmations;// Confirmation count
}
Functions:
FunctionAccessDescription
submitTransaction(to, value, data)OwnerSubmit a new transaction
confirmTransaction(txId)OwnerConfirm a pending transaction
revokeConfirmation(txId)OwnerRevoke your confirmation
executeTransaction(txId)OwnerExecute if enough confirmations
getTransactionCount()ViewTotal transaction count
getTransaction(txId)ViewGet transaction details
Events: Deposit, Submission, Confirmation, Revocation, Execution, ExecutionFailure The wallet accepts ETH via the receive() function, emitting a Deposit event.

Deployment

Deploy Token

TOKEN_NAME="MyToken" TOKEN_SYMBOL="MTK" INITIAL_SUPPLY="1000000" \
  npx hardhat run scripts/deploy-token.js --network localhost
Environment variables:
VariableDefaultDescription
TOKEN_NAMEToken name
TOKEN_SYMBOLToken symbol
INITIAL_SUPPLYInitial supply (whole tokens)
RPC_URLhttp://localhost:8545Chain RPC
PRIVATE_KEYDeployer private key

Setup Vesting

npx hardhat run scripts/setup-vesting.js --network localhost