Staking TNZO
Tenzro's StakingManager bonds TNZO behind validators, model providers, and TEE providers. Stake earns APY based on the lock period you choose, voting power scales linearly with your bonded amount, and the consensus layer slashes 10% of a validator's stake on equivocation. This tutorial walks the three RPCs you actually need: tenzro_stake, tenzro_getVotingPower, and tenzro_unstake.
What You'll Build
- Bond TNZO via
tenzro_stakewith an optional lock period - Inspect your stake position and voting power via
tenzro_getVotingPower - Initiate a 7-day unbond via
tenzro_unstake - Understand how validator equivocation triggers a 10% slash
Economics
Lock period Base APY
───────────── ────────
None (flexible) 5.0%
1–30 days 5.0%
31–90 days 7.5%
91–180 days 10.0%
181–365 days 12.5%
365+ days 15.0%
Minimum stake: 1000 TNZO (CLI-enforced floor)
Unbonding: 7 days
Early-exit: 25% penalty on staked principal (force=true)- Provider types:
validator(block production),inference(model serving),tee(confidential compute) - Voting power: 1 TNZO bonded = 1 unit of voting power, used by on-chain governance
- Slashing: 10% of bonded stake is slashed on consensus equivocation, enforced by
StakingSlashingCallbackintenzro-node
Step 1: Stake TNZO
tenzro_stake([{
"amount": "1000.0", // TNZO (decimal string, 18-decimal precision)
"provider_type": "validator", // "validator" | "inference" | "tee"
"lock_days": 90 // optional — boosts APY
}])
-> {
stake_id: "stake-01HR...",
transaction_hash:"0x...",
status: "active"
}The CLI enforces a 1000 TNZO floor for new positions. provider_type defaults to validator; pass inference or teeif you're bonding behind those provider roles instead.
Step 2: Read Your Position
tenzro_getVotingPower(["0xabc..."])
-> {
address: "0xabc...",
total_staked: "1000.0",
voting_power: "1000.0",
rewards: "12.34",
apy: "10.0",
is_locked: true,
lock_remaining_days: 82,
active_stakes: [
{
stake_id: "stake-01HR...",
amount: "1000.0",
provider_type: "validator",
apy: "10.0",
lock_remaining: "82d"
}
],
unbonding_stakes: []
}tenzro_getVotingPower is the single read endpoint for everything stake-related: bonded total, accrued rewards, lock countdown, the per-stake breakdown, and any unbonding stakes still in the 7-day cooldown.
Step 3: Unstake
tenzro_unstake([{
"amount": "500.0",
"force": false // true = withdraw during lock with 25% penalty
}])
-> {
transaction_hash: "0x...",
unbonding_period: "7d",
available_after: "2026-05-06T12:00:00Z"
}Unbonding takes 7 days. If your stake is still inside its lock period, the call returns an error unless you pass force: true— which triggers a 25% penalty on the principal.
Step 4: Slashing
// Slashing flow when a validator equivocates:
//
// 1. EquivocationDetector in tenzro-consensus fires on conflicting votes
// at the same view+height
// 2. The detector emits Evidence which the consensus engine surfaces
// to the registered SlashingCallback
// 3. tenzro-node's StakingSlashingCallback bridges to
// StakingManager::slash(validator, 10%) in tenzro-token
// 4. The validator's bonded stake is reduced 10% and they are removed
// from the active set for the current epoch
//
// All of this happens at the consensus + token layer — there is no
// separate slashing RPC. To see your stake balance after a slash event,
// re-query tenzro_getVotingPower.Step 5: CLI
# Stake 1000 TNZO as a validator with a 90-day lock
tenzro stake deposit 1000 --provider-type validator --lock-days 90
# Show your staking position (uses tenzro_getVotingPower under the hood)
tenzro stake info --address 0xabc...
# Withdraw 500 TNZO (must wait out lock or pass --force for 25% penalty)
tenzro stake withdraw 500
# Force-withdraw during the lock period
tenzro stake withdraw 500 --force
# Withdraw all stakeable balance
tenzro stake withdraw allStep 6: TypeScript SDK
import { TenzroClient } from "@tenzro/sdk";
const client = new TenzroClient();
// 1. Stake 1000 TNZO with a 90-day lock for 10% APY
const stake = await client.staking.stake({
amount: "1000.0",
provider_type: "validator",
lock_days: 90,
});
console.log("stake id:", stake.stake_id);
// 2. Read voting power and accrued rewards
const power = await client.staking.getVotingPower({ address: myAddr });
console.log("staked:", power.total_staked, "rewards:", power.rewards);
// 3. After the lock period, withdraw
const exit = await client.staking.unstake({ amount: "500.0", force: false });
console.log("available after:", exit.available_after);Note on liquid staking. A rebasing LiquidStakingPool with an stTNZO receipt token exists in the tenzro-token crate (see crates/tenzro-token/) but is not yet exposed via JSON-RPC, CLI, or SDK. Until it is, the staking flow above — direct bonding via tenzro_stake with optional lock periods — is the supported path.
What You Learned
- Three RPCs cover the surface:
tenzro_stake,tenzro_getVotingPower,tenzro_unstake - Lock periods boost APY from 5% (flexible) up to 15% (365+ days)
- Voting power = bonded TNZO — staking is the only path to on-chain governance weight
- Equivocation slashes 10% at the consensus layer via
StakingSlashingCallback
Next Steps
- See the Validator Node tutorial to run the validator your stake bonds behind
- See the Governance Voting tutorial — bonded stake is voting power
- Read the Tokenomics reference