Understanding APR Calculation for ZIGChain Staking
When staking assets on ZIGChain, one of the most important factors to consider is the Annual Percentage Rate (APR), as it determines the efficiency and profitability of staking.
This article explains how APR will be calculated for ZIGChain, breaking down key concepts such as annual provisions, community tax, bonded tokens ratio, and the difference between nominal and actual APR.
What is APR in ZIGChain Staking?
For users staking on ZIGChain, APR reflects the interest earned on bonded assets over a year. The calculation first derives Nominal APR, then adjusts it to obtain Actual APR (reflecting live network conditions), and —on validator pages— Final APR (after that validator’s commission).
1) Nominal APR
The nominal APR is the theoretical rate based on protocol issuance (inflation or annual provisions) and staking participation (bonded ratio)
- Includes: Community tax adjustment
- Excludes: Real-time block production and validator commissions
There are two equivalent ways to compute Nominal APR:
Inflation form (i)
Nominal APR = (Inflation Rate × (1 - Community Tax)) / Bonded Tokens Ratio
Annual Provisions form (AP)
Nominal APR = (Annual Provisions × (1 - Community Tax)) / Bonded Tokens
These two formulas are equivalent because:
Annual Provisions = Inflation Rate × Total Supply
(AP × (1 - ct)) / Staked = (i × TotalSupply × (1 - ct)) / Staked
= (i × (1 - ct)) / (Staked / TotalSupply)
To fully grasp both formulas, it is essential to understand the following parameters:
| Parameter | Description |
|---|---|
annual provisions | Number of ZIG tokens the network mints in one year (ZIG/year). |
bonded_tokens | Total ZIG actively staked (bonded). |
bonded_tokens ratio | Percentage of total ZIG that is actively staked: Bonded / Total Supply. |
community_tax | Portion of staking rewards allocated for network development and governance. More here. |
inflation rate | Percentage of tokens issued annually relative to the total supply. |
Some values may change via governance proposals. Always confirm using the CLI or API.
2) Actual APR
The actual APR is the Nominal APR adjusted by how many blocks were actually produced versus the target. If the network recently produced fewer (or more) blocks than the “expected per year,” the realized rewards rate changes accordingly.
The calculation is as it follows:
Actual APR accounts for real network conditions, such as block-minting speed:
Actual APR = Nominal APR × (Observed Blocks per Year / Expected Blocks per Year)
| Factor | Description |
|---|---|
| Block time variations | Real block production (Observed) may differ from the target (Expected) due to network conditions and upgrades. |
3) Final APR (Per-Validator Display)
The Final APR is the rate a delegator actually earns after the chosen validator’s commission.
This is the calculation to obtain it:
Apply the validator’s commission:
Final APR = Actual APR × (1 - Validator's Commission)
Since validator commissions vary, users can optimize rewards by selecting validators with lower fees. However, commission is not the only factor to consider:
- Reliability & Performance – High uptime and secure infrastructure help ensure consistent rewards.
- Governance Participation – Validators active in governance, aligned with your values.
- Decentralization – A diverse validator set strengthens security and resilience.
Verifiability and Transparency
This methodology is fully transparent and reproducible with on-chain data. Anyone can verify the inputs using simple CLI commands. In other words, the APR shown in the ZIGChain Hub is not a black box: it’s a deterministic computation based on values you can independently query at any time.
Units: On-chain amounts are in uzig.
Annual Provisions
- Mainnet
- Testnet
- Local
zigchaind query mint annual-provisions --chain-id zigchain-1 --node https://public-zigchain-rpc.numia.xyz
zigchaind query mint annual-provisions --chain-id zig-test-2 --node https://public-zigchain-testnet-rpc.numia.xyz
zigchaind query mint annual-provisions --chain-id zigchain-1 --node http://localhost:26657
Inflation
- Mainnet
- Testnet
- Local
zigchaind query mint inflation --chain-id zigchain-1 --node https://public-zigchain-rpc.numia.xyz
zigchaind query mint inflation --chain-id zigchain-1 --node https://public-zigchain-testnet-rpc.numia.xyz
zigchaind query mint inflation --chain-id zigchain-1 --node http://localhost:26657
Community Tax
- Mainnet
- Testnet
- Local
zigchaind query distribution params --chain-id zigchain-1 --node https://public-zigchain-rpc.numia.xyz
zigchaind query distribution params --chain-id zigchain-1 --node https://public-zigchain-testnet-rpc.numia.xyz
zigchaind query distribution params --chain-id zigchain-1 --node http://localhost:26657
Bonded Tokens
- Mainnet
- Testnet
- Local
zigchaind query staking pool --chain-id zigchain-1 --node https://public-zigchain-rpc.numia.xyz
zigchaind query staking pool --chain-id zigchain-1 --node https://public-zigchain-testnet-rpc.numia.xyz
zigchaind query staking pool --chain-id zigchain-1 --node http://localhost:26657
Blocks per year (Expected)
- Mainnet
- Testnet
- Local
zigchaind query mint params --chain-id zigchain-1 --node https://public-zigchain-rpc.numia.xyz
zigchaind query mint params --chain-id zigchain-1 --node https://public-zigchain-testnet-rpc.numia.xyz
zigchaind query mint params --chain-id zigchain-1 --node http://localhost:26657
Blocks per year (Observed)
On the Hub APR calculation, OBSERVED_BLOCKS_PER_YEAR=12,000,000 is used.
- Mainnet
- Testnet
- Local
RPC=https://public-zigchain-rpc.numia.xyz
CHAIN=zigchain-1
YEAR_SECS=31557600
if command -v gdate >/dev/null 2>&1; then D=gdate; else D=date; fi
OBS=0
for WIN in 100000 50000 20000 10000 5000 2000 1000 500 200 100; do
H=$(curl -s "$RPC/status" | jq -r '.result.sync_info.latest_block_height // 0')
[[ "$H" =~ ^[0-9]+$ ]] || { echo "RPC/status not reachable"; break; }
H0=$(( H>WIN ? H-WIN : 1 ))
T1=$(curl -s "$RPC/block?height=$H" | jq -r '.result.block.header.time // empty')
T0=$(curl -s "$RPC/block?height=$H0" | jq -r '.result.block.header.time // empty')
[[ -n "$T1" && -n "$T0" ]] || continue
t1=$($D -d "$T1" +%s 2>/dev/null || echo 0)
t0=$($D -d "$T0" +%s 2>/dev/null || echo 0)
(( t1>t0 )) || continue
dt=$((t1 - t0))
db=$((H - H0))
OBS=$(( db * YEAR_SECS / dt ))
echo "ObservedBlocksPerYear=$OBS (window=$WIN)"
break
done
RPC=https://public-zigchain-testnet-rpc.numia.xyz
CHAIN=zig-test-2
YEAR_SECS=31557600
if command -v gdate >/dev/null 2>&1; then D=gdate; else D=date; fi
OBS=0
for WIN in 100000 50000 20000 10000 5000 2000 1000 500 200 100; do
H=$(curl -s "$RPC/status" | jq -r '.result.sync_info.latest_block_height // 0')
[[ "$H" =~ ^[0-9]+$ ]] || { echo "RPC/status not reachable"; break; }
H0=$(( H>WIN ? H-WIN : 1 ))
T1=$(curl -s "$RPC/block?height=$H" | jq -r '.result.block.header.time // empty')
T0=$(curl -s "$RPC/block?height=$H0" | jq -r '.result.block.header.time // empty')
[[ -n "$T1" && -n "$T0" ]] || continue
t1=$($D -d "$T1" +%s 2>/dev/null || echo 0)
t0=$($D -d "$T0" +%s 2>/dev/null || echo 0)
(( t1>t0 )) || continue
dt=$((t1 - t0))
db=$((H - H0))
OBS=$(( db * YEAR_SECS / dt ))
echo "ObservedBlocksPerYear=$OBS (window=$WIN)"
break
done
RPC=http://localhost:26657
CHAIN=zigchain-1
YEAR_SECS=31557600
if command -v gdate >/dev/null 2>&1; then D=gdate; else D=date; fi
OBS=0
for WIN in 100000 50000 20000 10000 5000 2000 1000 500 200 100; do
H=$(curl -s "$RPC/status" | jq -r '.result.sync_info.latest_block_height // 0')
[[ "$H" =~ ^[0-9]+$ ]] || { echo "RPC/status not reachable"; break; }
H0=$(( H>WIN ? H-WIN : 1 ))
T1=$(curl -s "$RPC/block?height=$H" | jq -r '.result.block.header.time // empty')
T0=$(curl -s "$RPC/block?height=$H0" | jq -r '.result.block.header.time // empty')
[[ -n "$T1" && -n "$T0" ]] || continue
t1=$($D -d "$T1" +%s 2>/dev/null || echo 0)
t0=$($D -d "$T0" +%s 2>/dev/null || echo 0)
(( t1>t0 )) || continue
dt=$((t1 - t0))
db=$((H - H0))
OBS=$(( db * YEAR_SECS / dt ))
echo "ObservedBlocksPerYear=$OBS (window=$WIN)"
break
done
Expected output: ObservedBlocksPerYear=XXXXXXXX
Units: On-chain amounts are in uzig.
Conclusion
ZIGChain’s staking APR is determined by multiple factors, including issuance (via inflation or annual provisions), staking participation (bonded ratio), and live network conditions (block production). Nominal APR is theoretical; Actual APR adjusts for observed vs. expected blocks; and Final APR further reflects a validator’s commission.
By understanding these factors, ZIGChain users can make informed staking decisions for maximum profitability.