Skip to content

Claiming Rewards

What is "Proof of Verifiable Work"?

Proof of Verifiable Work (PoVW), a novel invention within Boundless, is a permissionless incentive mechanism which enables provers to be rewarded in $ZKC in exchange for their proving work on the Boundless marketplace or elsewhere. Provers generating unique zero-knowledge proofs are rewarded with $ZKC. This page explains the process of claiming PoVW $ZKC rewards.

Prerequisites

Install the latest release

PoVW was added to RISC Zero’s zkVM (R0VM) in version 3.0.1. To enable PoVW within Bento, requires release v0.14.0 and above.

To install the latest release, and use the helpful setup script, provers can follow the instructions on the Quick Start before continuing with the next step.

Make sure to have the Boundless CLI installed

Provers use the Boundless CLI to stake $ZKC, prepare work log updates, and submit them onchain. To install the Boundless CLI (and build with CUDA support), run:

cargo install --locked --git https://github.com/boundless-xyz/boundless boundless-cli --branch release-1.0 --bin boundless -F cuda

Install the latest version of Foundry

Some commands in this tutorial use cast from the Foundry toolkit. This is not necessary, but it will make some CLI commands more straightforward.

Install the latest version of Rust

Follow the instructions here.

Install the latest version of rzup

Follow the instructions here.

Install risc0-groth16 using rzup

Run the following:

rzup install risc0-groth16

Install all the necessary NVIDIA drivers

apt install nvidia-cuda-toolkit build-essential libssl-dev cuda-toolkit-13-0 nvidia-open

Update $PATH and export the necessary CUDA flags

export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
export NVCC_APPEND_FLAGS="--generate-code arch=compute_75,code=sm_75 --generate-code arch=compute_86,code=sm_86 --generate-code arch=compute_89,code=sm_89 --generate-code arch=compute_90,code=sm_90 --generate-code arch=compute_120,code=sm_120"

Stop Bento Safely

To enable PoVW in Bento, first make sure to stop Bento safely. This ensures that any in-progress proving jobs are completed before terminating the proving process. If Bento is backing the Broker, please carry out Step 1 from Safe Upgrade Steps and then return to this page.

If Bento is running without the Broker, Bento can be safely stopped with:

just bento down

Specify the Log ID Address

Before starting Bento again, provers need to enable the PoVW feature. This requires a valid Ethereum address set to the POVW_LOG_ID environment variable. It is recommended to set this directly with your compose.yml file:

x-base-environment: &base-environment
    DATABASE_URL: postgresql://${POSTGRES_USER:-worker}:${POSTGRES_PASSWORD:-password}@${POSTGRES_HOST:-postgres}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-taskdb}
  REDIS_URL: redis://${REDIS_HOST:-redis}:6379
  S3_URL: http://${MINIO_HOST:-minio}:9000
  S3_BUCKET: ${MINIO_BUCKET:-workflow}
  S3_ACCESS_KEY: ${MINIO_ROOT_USER:-admin}
  S3_SECRET_KEY: ${MINIO_ROOT_PASS:-password}
  RUST_LOG: ${RUST_LOG:-info}
  RISC0_HOME: /usr/local/risc0
  RUST_BACKTRACE: 1
  POVW_LOG_ID: "0x1234...5678"

Provers will need the private key for this address when using the PoVW CLI to prepare and submit valid work to the PoVW contracts. Please see Provers submit a Work Log Update for more information.

Export the PRIVATE_KEY and RPC_URL environment variables

Export the private key for the POVW_LOG_ID, and a valid RPC endpoint URL for Ethereum mainnet:

export PRIVATE_KEY=[PRIVATE_KEY]
export RPC_URL=[RPC_URL]

Start Bento

Once enabled, Bento can be run as normal with:

just bento

Or if running the broker as well:

just broker

will start both the broker and Bento.

Before continuing with the tutorial, it is recommended to read both the Terminology and Reward Claiming Workflow sections before running the commands listed below.

Claiming PoVW rewards

Staking $ZKC

Before provers can begin contributing work to claim PoVW rewards, they must stake $ZKC. The amount of PoVW rewards that provers claim every epoch is determined by the amount of $ZKC they have staked. This is currently set to staked amount / 15. Therefore if a prover has staked 150 $ZKC, they are eligible to receive a maximum of 10 $ZKC every epoch. For further details, please see Staking $ZKC.

Once staked, provers are eligible for $ZKC rewards effective immediately i.e. starting from the reward epoch they staked in; reward epochs are approximately 2 days long.

First, make sure to set a valid RPC URL environment variable for Ethereum mainnet:

export RPC_URL=https://...

To check the current $ZKC balance of POVW_LOG_ID:

boundless zkc balance ${POVW_LOG_ID:?} --rpc-url ${RPC_URL}

To stake 100 $ZKC, run the following command:

boundless zkc stake --amount $(cast parse-units 100 18)

Start Proving

Provers are now ready to run proving workloads with PoVW enabled; this can be done by running a prover on the Boundless marketplace or elsewhere.

For each proving job, R0VM will automatically generate work receipts. These work receipts track the amount of proving work done. Each epoch, provers will need to submit their accumulated work to the PoVW accounting smart contract. To do this, provers must use the PoVW CLI and run the following three commands, prepare, submit and claim.

Create and Update the Work Log

Once provers have run some jobs, they can create a new work log (i.e. state file) from receipts stored in Bento using prepare:

boundless povw prepare --new ${POVW_LOG_ID} --state ${STATE_FILE_LOCATION} --from-bento

where ${STATE_FILE_LOCATION} is something like: ~/folder/state.bin. Please note that this state file is very important and it should be kept in a durable location. Please see Keeping the State File Safe.

prepare compresses all work receipts and stores the work log update to the state file. This process is entirely local (i.e. it does not send any transaction). For this work to be eligible for $ZKC rewards from the PoVW contract, this work log update must now be sent onchain.

Provers only specify the --new ${POVW_LOG_ID} flag once, this is necessary to create the state file for that specific Log ID. Once the state file is created, for any further updates to the work log, run the following:

boundless povw prepare --state ${STATE_FILE_LOCATION} --from-bento

Send the Work Log Update Onchain

After running prepare, provers are ready to post the work log update onchain:

boundless povw submit --state ${STATE_FILE_LOCATION} --rpc-url ${RPC_URL}

Claiming Rewards

After the reward epoch has finalized, rewards can be claimed with:

boundless povw claim --log-id ${POVW_LOG_ID} --beacon-api-url${BEACON_CHAIN_RPC_ENDPOINT} --rpc-url ${RPC_URL}

Checking Details of Current Reward Epoch

If the reward epoch has not been finalized yet, provers can check details of the the current epoch:

boundless zkc get-current-epoch

This will return the epoch number; this epoch number can be passed into the following command to get the end time for the current epoch:

boundless zkc get-epoch-end-time <EPOCH_NUMBER>

Terminology

TermDescription
Log IDThis is the Ethereum address set with the POVW_LOG_ID environment variable. This address can be the same as the one used for a prover on the Boundless Market, but it doesn't have to be. See Recommended Practices for more information.
Work ReceiptsFor each proving workload, PoVW generates work receipts alongside the expected ZK proof. These work receipts are compressed into a “work log” update to post onchain. This work log update represents the combined work of all compressed work receipts. Work receipts are compressed using the prepare CLI command, and this process is entirely local.
Work LogThe work log is a record of work tracked against a specific log ID i.e. it represents a tally of all work done by that address. A work log commitment prevents “double-spending” of verifiable work when claiming PoVW rewards. The work log is updated using the submit CLI command, which takes a work log update (generated by prepare) and updates the commitment onchain to reflect all the work done by the log ID since the last update.
Reward EpochThe PoVW reward epoch is approximately 2 days. Verifiable work submitted within a given epoch is eligible for that epoch’s reward emissions. To be eligible for these rewards, a prover must stake an amount of $ZKC that scales with the size of their rewards for a given epoch. For more information, please see this blog post.

Reward Claiming Workflow

Staking Requirements

  • Provers must stake $ZKC to be eligible for PoVW rewards.
  • Before staking, any proving work done is not eligible for rewards.
  • Once provers have staked, any work done immediately after staking is eligible for rewards in the current reward epoch.

Overview

Provers generate ZK proofs

Generating any ZK proofs, with the POVW feature enabled in Bento, will generate work receipts.

Provers compress work receipts with prepare

The prepare command compresses all local work receipts to reflect work done during any given epoch - this update is stored in a local “state” file.

Provers submit a work log update with submit

Towards the end of an epoch, the prover must verify their work done to the PoVW contracts using the submit command. This will sign the work log update using the Log ID’s private key and post the update to the PoVW contracts.

Provers wait for current epoch to finalize

The prover waits for the current reward epoch to finalize. This allows all work log updates to be tallied, and all the respective rewards for each log ID to be calculated.

To check details of the current epoch, please see Checking Details of Current Reward Epoch,

Provers claim rewards with claim-rewards

Once the epoch has been finalized, the claim command can be used to claim any unclaimed rewards; claim uses Steel to query all work log updates and verify reward calculations.

claim requires both a valid archive node RPC endpoint and a Beacon Chain RPC endpoint (Quicknode offers both types of nodes with their paid plan).

Claiming rewards does not have to be done every epoch; all unclaimed rewards from past epochs will be claimed automatically on the next valid claim call.

Recommended Practices

Key Separation

In PoVW, the prover specifies the Log ID which must be a valid Ethereum address. This does not have to be the same as the $ZKC staking wallet address or a Boundless prover address, though it can be used for all three purposes. Note that PoVW rewards are eligible for all verifiable work, not solely work done to prove Boundless market orders. Therefore, provers not connected to the Boundless market are still eligible for $ZKC rewards, provided they are proving during the epoch and they have staked $ZKC.

Separating the Staking Wallet from the Log ID

When enabling PoVW in Bento, provers specify the following environment variables:

export POVW_LOG_ID="0x0000...0000"
export POVW_PRIVATE_KEY="..."

To stake from a separate wallet, provers may additionally specify:

export ZKC_WALLET_ADDRESS="0x0000...0000"
export PRIVATE_KEY="..."

Provers can now follow the staking instructions to stake $ZKC from the ZKC_WALLET_ADDRESS. Once staked, provers must delegate rewards i.e. associate the POVW_LOG_ID with ZKC_WALLET_ADDRESS. This is done with the following command:

boundless zkc delegate-rewards ${POVW_LOG_ID}

This command uses the PRIVATE_KEY environment variable to send a transaction onchain, therefore funds are required on ZKC_WALLET_ADDRESS.

Once the rewards are delegated, the prover can continue with the normal reward claiming workflow and they can start proving.

Separating the Staking Wallet from the Value Recipient

Additionally, the prover can specify a separate Ethereum address to receive the $ZKC reward. By default this is the log ID, but you can override it with --value-recipient <address> when running send‑update.

Separating Keys when runnning a Boundless Prover

Since many Boundless provers run clusters on hosted cloud providers, and because the private key must be in plaintext when starting the broker, the security of this wallet depends on your trust in the cloud provider. Therefore, for provers running large proving/ZK-mining clusters with large expected $ZKC reward amounts, it is not recommended to use your Boundless proving address as the value recipient. If the key is compromised, this can lead to a loss of rewards and require new wallet setup to resume proving.

At the minimum, we recommend most provers separate their value recipient address, such that:

  • Boundless Prover Address + Log ID Address can be the same
  • Value Recipient is a separate address

This setup allows the proving cluster to prove orders on the Boundless market and generate and post work log updates onchain to be eligible for rewards. It also means that after running claim, the reward $ZKC is transferred to a separate address. Claiming rewards is a permissionless process and does not require access to the private key for the Log ID.

Keeping the State File Safe

prepare uses a state file to track compressed work receipts. Loss of this state file will result in the loss of all work that is not submittedfor the respective Log ID, meaning rewards for any work done since the last work log update (via submit) will be lost. In this scenario, a new work log ID must be specified for Bento, and Bento should be restarted to allow further work to be recorded properly against the new Log ID. To avoid this scenario, it is recommended to store the state file in a durable location.