Skip to content

Wucklace/OnchainTokenomist

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OnchainTokenomist

Verifiable on-chain tokenomics — transforming token economies into programmable, executable systems.


Overview

OnchainTokenomist is a permissionless, modular smart contract protocol for tier-based token economies with category-based vesting. It replaces traditional off-chain, spreadsheet-based mechanics with fully programmable, composable, and executable tokenomics logic.

At its core, the protocol issues soulbound ERC-721 passes as the complete on-chain record of a holder's economic entitlement. Each pass carries its full state — allocation per pass, vesting schedule, amount claimed, and amount remaining — keyed by token ID, not by address. The holder's address is only verified at claim time to confirm pass ownership, never as the source of entitlement. Holding the pass is the right.

Each pass belongs to a tier — a defined allocation bucket within a category. Categories group related tiers under a shared vesting schedule, and together they compose the vault: the complete on-chain record of a project's entire token economy. The vault exposes a live, queryable summary of everything — total supply, per-category and per-tier allocations, amount claimed, and amount locked or unlocked. There is no off-chain source of truth — the vault is the source of truth.

What separates OnchainTokenomist from conventional tokenomics systems is that nothing lives off-chain. The entire economic logic — allocation, vesting, distribution authority — is encoded, enforced, and verifiable on-chain, with execution that can be delegated without introducing control or discretion.

That delegation is handled by an optional AI agent executor — a programmable address that performs operational tasks on behalf of the creator: composing recipient sets, generating Merkle proofs, submitting proposals, and triggering minting. Approval authority stays exclusively with human admin signers where configured.

This is what on-chain tokenomics infrastructure means: not a tool for sending tokens, but a system for encoding, enforcing, and verifying a project's entire economic logic on-chain — allocation rules, vesting schedules, distribution authority, and execution flow — all immutable, queryable, and autonomous-ready from day one.


Use Cases

OnchainTokenomist is designed around a single flexible primitive — the vault. The same infrastructure serves three distinct use cases, each defined entirely by how the vault is configured at creation.

Token Locker

A single category with one tier, vesting disabled, and startBlock set to the intended unlock block. The deposited amount is locked on-chain and released in full at the defined block. No vesting, no distribution mechanics — just a cryptographically enforced time lock with a verifiable on-chain record.

Multi-Lock

A single category with multiple tiers, each with its own allocation and unlock block. Useful for projects that need to lock different amounts across different schedules — team allocations, investor tranches, reserve funds — each enforced independently within the same vault.

Tokenomics / Distribution

The full protocol — multiple categories, each with its own tier structure and vesting schedule. Each category is self-contained: cliff, duration, interval, and initial release configured independently. Passes are issued to recipients as the on-chain record of their entitlement, with vesting enforced and claims settled entirely on-chain.


Regardless of configuration, every vault is a live, queryable on-chain record of its token economy — total supply, per-category and per-tier allocations, amount claimed, and amount locked or unlocked. There is no off-chain source of truth.


The Problem It Solves

Traditional tokenomics is broken:

  • Allocations live in spreadsheets, not on-chain — unverifiable and mutable
  • Vesting is enforced off-chain, relying on team trust with no cryptographic guarantee
  • Economic records are opaque — there is no verifiable on-chain source of truth for what was promised, how many tokens are locked, how many are vesting, and how many have been claimed
  • No on-chain checks and balances — the same party that controls the treasury also executes distributions unilaterally, with no independent approval or verifiable audit trail

OnchainTokenomist replaces all of this with a verifiable on-chain tokenomics infrastructure — one where every allocation, every vesting schedule, and every claim is recorded, enforced, and queryable entirely on-chain.


Key Concepts

Vault

A vault is the root tokenomics object — the complete on-chain record of a project's entire token economy, exposing a live, queryable summary of every allocation, vesting schedule, claim, and locked or unlocked amount across every category and tier.

Before creation, the creator defines every parameter — token address, total amount, tier structure, vesting schedules, optional executor, and admin configuration — and submits them in a single atomic transaction. A small registration fee in the chain's native token is required at creation time.

At creation, the contract pulls the full token amount from the creator's wallet, locks the configuration, and emits the vault. From this point everything is immutable — allocations, tiers, vesting parameters, and admin roles are permanently fixed on-chain and cannot be changed.

Post-creation, the only action available to the creator is pass distribution — minting passes to recipients within the defined tier supply caps. Once all passes across all categories are fully distributed, the vault status automatically transitions to finalized and no further minting is possible.

A vault is structured around categories — logical groupings of tiers such as Team, Investors, Community, or Builder. Each category contains tiers: defined allocation buckets with a per-pass allocation and max supply (e.g. Diamond, Gold, Silver). Every category carries its own vesting schedule — cliff, duration, interval, and initial release — making each one fully self-contained. A change in one category's vesting never affects another.

Vaults are optionally configured with up to two admins, forming a dual-approval governance layer over pass distribution. Where no admins are configured, the creator mints directly. An AI agent executor can also be configured — handling operational execution within the bounds defined at creation.

Soulbound Pass

Each pass is the complete on-chain record of a holder's economic entitlement within their tier — carrying its full state from the moment of minting until the final claim.

The pass is non-transferable — transferFrom and safeTransferFrom revert unconditionally — because the entitlement belongs to the pass, not the address. All state is tracked by token ID, never by address; the holder's address is only relevant at claim time to confirm ownership. Once the full allocation has been claimed, the pass burns automatically — the record is complete and nothing remains to track.

The pass is the only proof of entitlement.

Proposal Workflow (Team Vaults)

In team-mode vaults, minting requires an approved proposal. The creator or executor submits a proposal via proposeMintCategory() — each tier within the proposal carries its own Merkle root, with recipient verification handled on-chain at mint time. The proposal requires approval from all configured admins before mintPasses() can be called. Proposals expire if not fully approved within the deadline window.

Creator / Executor
       │
       ▼
proposeMintCategory()   ─────────────────────────────────────┐
       │                                                     │
       ▼                                                     │
  Pending Proposal                                 Auto-expires at deadline
       │
  ┌────┴────┐
  │         │
Admin1   Admin2
approve  approve
  │         │
  └────┬────┘
       │
  Fully Approved
       │
       ▼
mintPasses()  →  ERC-721 issued to recipients via Merkle proof

Direct Mint (Creator-Mode Vaults)

Vaults with no admins configured bypass the proposal workflow entirely. The creator or executor calls mintDirect() — no approval needed, no Merkle verification required.

Vesting & Claiming

Each category carries its own independent vesting schedule — configured at vault creation and enforced entirely on-chain. Parameters are defined per category:

Parameter Description
cliff Blocks after startBlock before any interval unlocks begin
duration Total vesting period in blocks, measured from startBlock
interval Unlock frequency — tokens vest in discrete steps every N blocks after the cliff
initialRelease Percentage unlocked immediately at startBlock, before the cliff
enabled Toggle — disabled means 100% liquid at startBlock

Pass holders call claim(tokenIds[]) to collect vested tokens. The contract calculates the vested amount at the current block, subtracts previously claimed amounts, and transfers the difference. Once fully claimed, the pass burns automatically.


Architecture

The contract is fully modular. All logic is split across inherited modules with no delegatecall or proxy patterns. A single BaseStorage contract declares the shared storage struct s — Solidity's C3 linearization guarantees all modules read and write the same storage slot in the final deployed contract.

BaseStorage.sol          ← shared storage `s`, all events, all errors
       │
       ├── VaultModule.sol       createVault()
       ├── ProposalModule.sol    proposeMintCategory(), approveMintProposal(), rejectMintProposal()
       ├── MintModule.sol        mintPasses(), mintDirect()
       ├── ClaimModule.sol       claim()
       └── ViewModule.sol        all read-only queries, all return structs

OnchainTokenomist.sol    ← inherits all modules + constructor + soulbound overrides

Libraries (compiler-inlined, no runtime delegation)

Library Purpose
StorageLib All storage structs and TokenomicsStorage definition
VestingCalculator Vesting math — calculateVested, getNextUnlockBlock, getVestedPercentage
ValidationLib Input validation — addresses, amounts, tier configs, vesting configs
FeeManager Registration fee collection and fee receiver management

Contract Interface

Vault

function createVault(
    address tokenAddress,
    uint256 amount,
    address admin1,
    address admin2,
    address executor,
    uint256 startBlock,
    TierConfigInput[] calldata tierConfigs,
    VestingConfigInput[] calldata vestingConfigs
) external payable returns (uint256 vaultId);

Proposals

function proposeMintCategory(uint256 vaultId, bytes32 category, TierBatch[] calldata tierBatches) external returns (uint256 proposalId);
function approveMintProposal(uint256 proposalId) external;
function rejectMintProposal(uint256 proposalId) external;

Minting

// Team vaults — requires approved proposal + Merkle proof per recipient
function mintPasses(uint256 proposalId, bytes32 tier, address[] calldata recipients, bytes32[][] calldata proofs) external;

// Creator-only vaults — no proposal, no proof required
function mintDirect(uint256 vaultId, bytes32 category, bytes32 tier, address[] calldata recipients) external;

Claiming

function claim(uint256[] calldata tokenIds) external;

Views

function getUserPasses(uint256[] calldata tokenIds) external view returns (UserPassInfo[] memory);
function getVaultSummary(uint256 vaultId) external view returns (VaultSummary memory);
function getVaultSummaries(uint256 startId, uint256 count) external view returns (VaultSummary[] memory);
function getVaultSummariesByCreator(address creator) external view returns (VaultSummary[] memory);
function getCategoryAllocation(uint256 vaultId, bytes32 category) external view returns (CategoryAllocation memory);
function getVaultCategoryAllocations(uint256 vaultId) external view returns (CategoryAllocation[] memory);
function getTierDetails(uint256 vaultId, bytes32 category, bytes32 tier) external view returns (TierDetails memory);
function getCategoryTierDetails(uint256 vaultId, bytes32 category) external view returns (TierDetails[] memory);
function getVestingSchedule(uint256 vaultId, bytes32 category) external view returns (VestingSchedule memory);
function getAdminPendingProposals(address admin) external view returns (ProposalInfo[] memory);
function getInvolvedProposals(address account) external view returns (ProposalInfo[] memory);
function getPlatformStats() external view returns (PlatformStats memory);

Security Properties

Every guarantee made by the protocol — immutability, verifiability, and trustless distribution — is backed by a specific on-chain mechanism. No property relies on off-chain enforcement or operator trust.

Property Mechanism
Pass-keyed entitlement All distribution state is keyed by token ID — allocation, vesting, and claimed amounts are tied to the pass, never to an address
Address touch on mint only Recipient addresses are written once to a reverse lookup index at mint time — no address is ever read for entitlement, access control, or claim calculation
Soulbound passes transferFrom and safeTransferFrom unconditionally revert
Reentrancy protection All stateful functions use OpenZeppelin ReentrancyGuard
Merkle-gated minting Each recipient verified against admin-approved Merkle root at mint time
Dual-admin approval Both admins must independently approve before any mint is permitted
Proposal deadlines Proposals auto-expire after a fixed block window — no stale approvals
Proposal rejection Either admin can permanently reject a proposal — rejected proposals cannot be executed
Supply enforcement mintedCount + batch.length > maxSupply reverts before any mint
Immutable vault config Allocations, tiers, vesting parameters, and admin roles are permanently fixed at creation — nothing can be changed post-deploy
Pass auto-burn Pass burns on full claim — no double-claim possible
Token safety All ERC-20 transfers use OpenZeppelin SafeERC20
Fee timelock Registration fee updates require a 604800 block timelock before taking effect
Category isolation Vesting schedules and supply caps are enforced per category — exhaustion or misconfiguration in one category cannot affect another
Executor bounds The executor cannot alter allocations, vesting parameters, or admin roles — it can only perform operational tasks within the bounds defined at creation
Vault finalization Once all passes across all categories are fully distributed, the vault status transitions to finalized — no further minting is possible under any condition

Deployment

constructor(
    address _feeReceiver,   // Address that receives vault registration fees
    uint256 _registrationFee // Fee in native token (wei) per vault creation
)

The constructor initializes all counters to 1 (nextVaultId, nextProposalId, nextTokenId) — ID 0 is reserved as a sentinel null value throughout the contract.


Testing

The test suite is designed to verify every protocol guarantee end-to-end — from vault creation and proposal flows to vesting enforcement, claim mechanics, and access control. Scripts are split into sequential flow tests and standalone scenario tests. Each script prints a full summary of what was tested at the end of its run.

What's Covered

Script Description
step1 Vault creation — full multisig (admin1 + admin2 + executor), token deployment, tier and vesting config
step2 Proposal flow — propose, dual-admin approve, Merkle-gated mint across Team, Advisors, and Community categories
step3 Vesting and claim — block progression to trigger interval unlocks, partial claims, full claims, pass burn confirmation
creator-vault Creator-only vault creation — no admins, executor-enabled
direct-mint Direct mint — creator and executor mint via mintDirect, no proposal or Merkle proof required
comprehensive-test Multi-vault scenarios — single admin, approve proposal, mint proposal, pending proposal, expired proposal, rejected proposal, cross-role minting, view function coverage
fee-manager Fee management and governance — propose/execute/cancel fee updates, timelock enforcement, fee receiver updates, governance transfer up to max limit
access-control Permission enforcement — NotAdmin, NotAuthorized, NothingToClaim reverts, pre-startBlock claim guard, burn confirmation

Sequential Flow

Runs as a single session — each step depends on state from the previous.

npx hardhat node
npm run deploy
npm run step1
npm run step2
npm run step3

Standalone Tests

Each requires a fresh node and redeploy — they create their own vaults and mine blocks independently.

# Creator-only vault flow
npx hardhat node
npm run deploy
npm run creator-vault
npm run direct-mint

# Fee & Governance
npx hardhat node
npm run deploy
npm run fee-manager

# Access Control & Locker
npx hardhat node
npm run deploy
npm run access-control

# Comprehensive multi-vault
npx hardhat node
npm run deploy
npm run comprehensive-test

Note: Always restart the Hardhat node and redeploy before each standalone test to ensure clean contract state, correct token IDs, and accurate block numbers.


Dependencies


License

MIT

About

Permissionless smart contract protocol for verifiable on-chain token economies — tier-based allocation, category-based vesting, soulbound ERC-721 passes, and dual-admin governance with AI executor support.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors