Skip to content

Vault, reward token, funding

Each project has its own ProjectVault on Sepolia, at an address fixed by the project id (CREATE2 from the vault factory). It holds the reward token, pays settled epochs, enforces the epoch cap and fee split, and lets you withdraw unused funds after a delay.

economics.reward_token can be any ERC-20 on Sepolia. Test NECTA (0x52efcdf0bd3ca7554c0dfb3141125b1a4d54eb7e) is the simplest: the faucet gives 1,000 NECTA per address every 24 hours. For larger budgets deploy your own test ERC-20 and mint it to yourself. Tokens with transfer fees are rejected by fund (UnsupportedToken).

epoch_cap = floor(daily_emission × epoch_secs / 86400) # the most one epoch can pay

The reference project sets daily_emission = 24,000 NECTA with 1-hour epochs, so epoch_cap = 1,000 NECTA. If the vault’s free balance drops below one epoch_cap, the project is underfunded: tasks still run, but as validator rounds that pay nobody, until you top up. Plan for several days of daily_emission.

Creating the vault is the one transaction you pay gas for (a very small amount of Sepolia ETH). It must be sent by the developer address, after the project is registered on-chain, and its configuration must match the manifest’s economics.

  1. Create the vault with ProjectVaultFactory.createVault(projectId, rewardToken, config), where config = (minerBp, developerBp, treasuryBp, epochSecs, epochCap, developerPayout). With Foundry’s cast:

    Terminal window
    FACTORY=0x4d6b1abf2475452acd904682144db283e039c46f
    NECTA=0x52efcdf0bd3ca7554c0dfb3141125b1a4d54eb7e
    RPC=https://ethereum-sepolia-rpc.publicnode.com
    PROJECT_ID=0x… # from prepare / your project page
    DEV=0x… # your developer address (also receives the developer share here)
    EPOCH_CAP=1000000000000000000000 # floor(daily_emission × epoch_secs / 86400)
    cast send $FACTORY \
    "createVault(bytes32,address,(uint16,uint16,uint16,uint32,uint256,address))" \
    $PROJECT_ID $NECTA "(8500,1000,500,3600,$EPOCH_CAP,$DEV)" \
    --rpc-url $RPC --account my-testnet-wallet

    cast call $FACTORY "predictVault(bytes32)(address)" $PROJECT_ID --rpc-url $RPC must print the same address as your manifest’s economics.vault. The call reverts with ProjectNotRegistered before registration is indexed on-chain, NotDeveloper from another address, and VaultExists if it already exists.

  2. Approve and fund. fund(amount) pulls tokens you approved:

    Terminal window
    VAULT=0x… # economics.vault
    AMOUNT=10000000000000000000000 # 10,000 tokens with 18 decimals
    cast send $NECTA "approve(address,uint256)" $VAULT $AMOUNT --rpc-url $RPC --account my-testnet-wallet
    cast send $VAULT "fund(uint256)" $AMOUNT --rpc-url $RPC --account my-testnet-wallet

    Anyone can fund a vault, so a sponsor or community can top it up too.

  3. Check runway.

    Terminal window
    cast call $VAULT "runwayEpochs()(uint256)" --rpc-url $RPC
    curl -s https://testnet-rpc.necter.network/v1/projects/$PROJECT_ID/economics

Each settled epoch reserves its gross amount. After the challenge window (1 hour):

  • miners claim their amounts with Merkle proofs (gasless through the Hub);
  • release(epoch) (callable by anyone) pays the developer share to developerPayout and the treasury share to the network treasury.

Only the developer can take money back out, with a delay so miners are never surprised:

Terminal window
cast send $VAULT "requestWithdraw(uint256)" $AMOUNT --rpc-url $RPC --account my-testnet-wallet
# after the withdraw delay (172,800 s = 48 h on the testnet):
cast send $VAULT "executeWithdraw()" --rpc-url $RPC --account my-testnet-wallet

Only the free balance (not amounts reserved for settled epochs) can be withdrawn. cancelWithdraw() cancels.

scheduleConfig(config) on the vault schedules a new (minerBp, developerBp, treasuryBp, epochSecs, epochCap, developerPayout) that activates after the registry’s activation delay. epochSecs can never change. Change the manifest’s consensus economics in a new version at the same time, so validators and the vault agree: Versions and activation.