Purpose

This document walks through the staking specification for Story. The goal is to provide clarity to network participants and technical partners on how Story’s staking mechanics work and how users can interface with our chain.

Tokenomics

Genesis

The story genesis allocation will consist of 1 billion tokens, distributed among ecosystem participants, the foundation, investors, and the core team. Please refer this document for the detailed Token Distribution.

Locked vs Unlocked tokens

Unlocked tokens have no restrictions imposed on them and can be used for gas consumption, transfers, and staking.

Unlike unlocked tokens, locked tokens cannot be transferred or traded and are unlocked based on an unlock schedule. However, locked tokens may be staked to earn staking rewards, with the locked staking reward rate being half of that of unlocked tokens.

Staked locked and unlocked tokens have the same voting power. That means that a validator with 100 staked locked tokens has the same network voting power as a validator with 100 staked unlocked tokens.

Both types of tokens can be slashed if their validators get slashed.

Token emissions

A fixed number of tokens will be allocated for emissions in the first year, with the quantity determined by the foundation at Genesis. For subsequent years, the number of emitted tokens will be controlled by an emissions algorithm whose parameters may be updated via governance or subject to change via hard forks. The emissions per block are controlled by the following two parameters:

  • blocks_per_year: 10368000 blocks
    • The number of blocks expected to be produced in a year
  • inflations_per_year: 20,000,000 tokens
    • The total number of inflationary tokens to be emitted in a year

New emissions will flow to two places:

  1. Block Rewards
  2. Community Pool

Token burn

Since Story uses a fork of geth as the execution client, the burning mechanism follows Ethereum’s EIP-1559.

Staking

🔗 Stake with the Staking Dashboard ↗️

Story supports the below staking-related operations

  • Create validator
  • Update validator commission
  • Stake
  • Stake on behalf
  • Unstake
  • Unstake on behalf
  • Redelegate
  • Redelegate on behalf
  • Set withdraw address
  • Set reward address
  • Unjail
  • Unjail on behalf

Before explaining the behavior of each of these operations, some high-level concepts like Token Staking Types, Validator Set Status, Unbonding, and Staking Period will be explained first:

Token Staking Types

As staking is enabled for both locked and unlocked tokens, validators must choose which type of token staking they want to support. Once a token staking type is selected, validators cannot switch to a different type.

Validator Set Status

In Story, validators are grouped into one of two sets, (1) the active (bonded) validator set, which participates in consensus and receives block rewards, or (2) the non-active (unbonded) validator set, which does not contribute to the consensus process. To be selected as part of the active validator set, a validator must be one of the top 64 validators ranked by staked tokens.

Unbonding

Unstaking for delegators is subject to an unbonding process. Users must wait for an unbonding time before any tokens return to their accounts.

This is the same for validators who self-delegate to themselves. They also need to go through the unbonding process when they want to unstake.

The unbonding time is 14 days. During the unbonding period, the delegator/validator will not earn block rewards. But they may still be slashed.

For each validator/delegator pair, the maximum ongoing unbonding transactions is 14. More unbonding requests beyond this limit will fail.

Staking period

Delegators can decide how flexible and how long they want to stake their tokens. By default, for both locked and unlocked tokens, delegators can stake and then unstake immediately and get their token back after the unbonding time. We call this flexible staking in this document.

For unlocked tokens, a few more fixed staking periods are supported: 90 days, 360 days, and 540 days. In this case, users can only call unstake after the staking period is mature. Any call earlier than the mature day will be discarded. Unstaking from a mature staking period is still subject to the unbonding process, meaning users will get their staked tokens back after 14 days of unbonding time.

Staking in these fixed staking periods earns more rewards. The longer the period, the bigger the reward weight multiplier. Reward multiplier for different periods:

  • Locked flexible period - 0.5
  • Flexible period - 1.0
  • 90 days - 1.1
  • 360 days - 1.5
  • 540 days - 2

For locked tokens, only flexible staking is allowed and the reward multiplier is 0.5. If a user delegates their locked tokens to a staking period, we will convert that to a flexible staking delegation.

After the staking period ends, users can choose not to unstake. In this case, they will continue earning the same reward rate based on the reward rate of the corresponding staking period until they unstake manually. They can unstake at any time after the staking period ends. For example, if the 1-year staking period’s reward rate is 0.02% per block, after staking for 1 year, users can still earn 0.02% per block of the reward until they unstake.

Decimal for stake amounts

The decimal for stake operations (stake, unstake, redelegate, etc.) is 9. If a user specifies a smaller value, the dust will be refunded back to the users. Or if there is no token transfer involved, the specified value will be rounded down to 9 decimals.

Staking Operations

Create validator

To become a validator, the validator must first run a validator node based on the latest released story binaries, then call the CreateValidator function with an initial staking amount, moniker, and commission rate. It also needs to set the max commission rate and max commission rate change to make sure it doesn’t change the commission rate later dramatically. The minimum commission rate that a validator can set is 5%.

The initial staking amount needs to be larger than a threshold, which is 1024 IP. The amount will be deducted from the caller’s wallet. It can only be staked to a flexible period.

If a validator tries to call create validator function the second time, it will be ignored.

Update validator commission

This operation allows validators to edit their validator commission rate. If the updated commission rate is larger than max commission rate or the commission rate change delta is larger than max commission rate change, the operation will fail.

A fee of 1 IP will be charged for updating a validator to prevent spamming. The fee will be burnt by the contract.

The commission rate can only be updated once per day. It will not throw an error from the contract. But it won’t take effect in the consensus layer.

Stake

Both the validator and delegator can stake tokens to a validator. A validator can stake to itself, which is called self-delegation. Users can decide if they want to stake with a fixed staking period or stake without a period (flexible staking).

If a fixed period is chosen, a delegation id will be returned to the users. Users must use this delegation id to unstake tokens from this stake operation. If flexible staking is chosen, the returned delegation id will be 0.

The staking amount needs to be larger than a threshold, which is 1024 IP.

If a delegator delegates to a non-existent validator, the tokens will NOT be refunded.

If users specify the token amount that has more than 9 decimal units, the actual staking amount will be rounded down to 9 decimal and refund the remaining back to the users.

Unstake

When staking without a staking period, users can unstake anytime. The tokens will be distributed to the user’s account after the unbonding time.

A fee of 1 IP will be charged for unstaking to prevent spamming. The fee will be burnt by the contract.

When staking with a staking period, users can only unstake after the staking period is mature. The tokens will be distributed to the user’s account after the unbonding time. Unstaking requests before the staking period matures will be ignored.

The minimum unstaking amount is 1024 IP. After the unstaking request is processed, if the remaining staked amount is less than 1024 IP, the remaining part will also be unstaked together.

The unstaking request will first go through the unbonding process, which is 14 days. After that, the unbonded requests are sent to a withdrawal queue, distributing a maximum of 32 withdrawals per block. If there are more than 32 withdrawal requests in the withdrawal queue, the next 32 withdrawal requests will be processed in the next block.

Partial unstake of a delegation is supported. For example, if a 1-year long delegation has 1 million tokens, after 1 year, users can unstake 500k from this delegation and keep the remaining staked to continue earning rewards.

Unstake can fail if the validator, delegator and delegation id passed in is incorrect.

Unstake can also fail if the maximum concurrent unbonding request (currently 14) has been reached for the validator/delegator pair.

If the unstake amount passed in is larger than the total unstakable tokens, the current total unstakable amounts will be unstaked. For example, if users unstake 1024 IP and only have 1023 IP stake, 1023 IP will be withdrawn.

If a validator exits, by either being offline and getting jailed, or not having enough stakes to be in the top 64 validator set, the delegators can unstake their tokens if the tokens are not in a staking period or their staking period is mature. Otherwise, delegators must wait until the staking period matures to unstake.

If users specify the token amount that has more than 9 decimal units, the actual unstaking amount will be rounded down to 9 decimal.

Redelegate

Redelegate operation allows a delegator to move its staked tokens from one validator to another. The tokens can be redelegated to the new validator immediately and start earning rewards. However, the redelegated tokens are still subject to the unbonding process, IF the source validator is in the active validator set or unbonding from the active validator set. During this 14 days unbounding time, it will be slashed if the original validator gets slashed.

A fee of 1 IP will be charged for redelegation to prevent spamming. The fee will be burnt by the contract.

The minimum redelegation amount is 1024 IP. If a delegator’s initial stake is 1024 IP but later gets slashed, it can still redelegate its tokens to another validator even if the token amount is less than 1024 IP.

Similarly to unstaking, if the redelegation amount passed in is larger than the total redelegatable tokens, the total redelegatable amounts will be redelegated. If the remaining balance after redelegation is less than 1024 IP, all remaining tokens will be redelegated together.

The delegation id will stay the same after the redelegation.

Redelegation has its own maximum ongoing unbonding transaction limit per delegator/source validator/destination validator pair, which is also 14.

Delegators can choose to redelegate their tokens to another active validator even if their tokens are still in an immature staking period. Their staking period maturation date and reward rate will stay the same.

Redelegation can only be triggered when the source and destination validators support the same token type.

If users specify the token amount that has more than 9 decimal units, the actual reledegated amount will be rounded down to 9 decimal.

Set withdrawal/reward address

Delegators can call the staking contract to set a withdrawal address. The unstaked tokens will be sent to this withdrawal address. Similarly, delegators can set a separate reward address. All reward distributions will be sent to this address.

A fee of 1 IP will be charged for updating either the withdrawal address or the reward address to prevent spamming. The fee will be burnt by the contract.

The address change will take effect in the next block.

Slash/Unjail

Slashing penalizes bad behaviors on the validators by slashing out a fraction of their staked tokens. Two types of behaviors can get slashed in Story: double sign and downtime.

  • double sign: If a validator double signs for a block, they will get slashed 5% of their tokens and get permanently jailed (called tombstoned).
  • downtime: If a validator is offline for too long and misses 95% of the past 28,800 blocks, they will get slashed 0.02% of their tokens and get jailed.

A validator will also get jailed after self-undelegation if the validator’s remaining self-delegation amount is smaller than the minimum self-delegation (1024 IP).

A jailed validator cannot participate in the consensus and earn any reward. But they can unjail themselves after a cooldown time, which is currently set to 10 minutes. After 10 minutes, it can call story’s staking contract to unjail itself IF their stake is more than minimum stake amount (1024 IP), after which it can participate in the consensus again if it’s still within the top 64 validators.

A jailed validator can still withdraw all their stakes.

Delegators can still stake and unstake from a jailed validator as long as there are remaining stakes on this jailed validator. The jailed validator will only be removed from the chain (hence not able to be staked/unstaked) when there is no remaining stake on it.

A fee of 1 IP will be charged for unjailing a validator to prevent spamming. The fee will be burnt by the contract.

On behalf functions

Most of the staking-related operations can be done from another wallet on behalf of the validators or delegators. Most of these on-behalf functions are permissionless since they spend tokens from the wallet that calls the on-behalf operations, not from the actual validators or delegators.

Add operator

If a delegator wants to allow another wallet to unstake or redelegate on their behalf, they must call the staking contract to add that wallet as the operator for their delegator. After that, the operator can unstake and redelegate the delegator’s tokens on behalf of the delegator.

The same applies to a validator who wants to allow another wallet to unjail on its behalf.

A fee of 1 IP will be charged for adding an operator.

An additional data field

Each function will include an additional unformatted data input field to accommodate potential future changes. It can avoid changing user interfaces in the future.

Validator key format

Validator public keys are secp256k1 keys. The keys have a 33 bytes compressed version and 65 bytes uncompressed version. When interacting with the story’s smart contracts, a 33 bytes compressed key is used to identify validators.

Rewards

Rewards Pool Allocation

For every block, a fixed proportion of token inflation will go to the rewards distribution pool, which will be shared among all 64 active validators according to each of their share weights. These allocated tokens will then be shared among the validator and its delegators in a fashion described by the next section. The validator share weight is calculated based on the total token staking amount, and whether or not the token staking type is locked or unlocked.

As an example, assume that we have 100 tokens allocated for the validator rewards distribution pool, and assume that we only have 3 active validators:

  • validatorA with 10 locked tokens staked
  • validatorB with 10 locked tokens staked
  • validatorC with 10 unlocked tokens staked

To calculate how many tokens each validator receives, we first calculate each of their weighted shares, which is defined as the number of staked tokens multiplied by their rewards multiplier (0.5 if staking locked tokens, 1 if staking unlocked tokens). This gives us:

  • validatorA with 10 * 0.5 = 5 shares
  • validatorB with 10 * 0.5 = 5 shares
  • validatorC with 10 * 1 = 10 shares

With the weighted and total shares calculated, we can then get the total number of inflationary tokens allocated for each validator:

  • validatorA with 100 * (5 / 20) = 25 tokens
  • validatorB with 100 * (5 / 20) = 25 tokens
  • validatorC with 100 * (10 / 20) = 50 tokens

The formula for calculating the total number of tokens allocated for a validator is as follows:

where

  • R_i is the total inflationary token rewards for validator i
  • S_i is the staked tokens for validator i
  • M_i is the rewards multiplier (0.5 for locked tokens, 1 for unlocked tokens)
  • R_total is the total inflationary tokens allocated for the rewards pool

Validator And Delegator Rewards

Total rewards allocations (whose calculations are shown in the prior section) for each validator are shared between the validator itself and all of its delegators:

  • The validator takes a fixed percentage commission, set by the validator itself
  • Remaining rewards are distributed among delegators according to their share weights

Calculation of delegator rewards is similar to that of validator rewards, where the proportion of tokens received for each delegator out of the remaining validator rewards is calculated based on each delegator’s staking multiplier (described in the staking section).

As an example, assume a validator has 100 total rewards allocated to it, with a validator commission of 20%, and 3 delegators delegating to it:

  • delegatorA with 10 tokens staked and a staking multiplier of 1
  • delegatorB with 10 tokens staked and a staking multiplier of 1
  • delegatorC with 10 tokens staked and a staking multiplier of 2

To calculate how many tokens each delegator receives, we first calculate each of their weighted shares, which is defined as the number of staked tokens multiplied by their staking rewards multiplier. This gives us:

  • delegatorA with 10 * 1 = 10 shares
  • delegatorB with 10 * 1 = 10 shares
  • delegatorC with 10 * 2 = 20 shares

With the weighted and total shares calculated, we can then get the total number of inflationary tokens allocated for each delegator, noting that the total number of tokens to be distributed among delegators is give by 100 - (100 * 0.20) = 80:

  • delegatorA with 80 * (10 / 40) = 20 tokens
  • delegatorB with 80 * (10 / 40) = 20 tokens
  • delegatorC with 80 * (20 / 40) = 40 tokens

The formula for calculating the delegator token reward can be found below:

where

  • D_i is the total inflationary token rewards for delegator i
  • S_i is the staked tokens for delegator i
  • M_i is the staked rewards multiplier for delegator i
  • R_total is the total inflationary tokens allocated for the validator
  • C is the commission rate for the validator

The validator commission is also treated as a reward and will follow the same auto-reward distribution rule described below. The minimal validator commission is set to 5% to avoid a cut-throat competition of lower commission rates among validators.

The reward calculation results will be rounded down to gwei. Anything smaller than 1 gwei will be truncated.

Auto reward distribution

The reward is accumulated per block and can be distributed per block. However, it will only be automatically distributed to the delegator’s account when it is larger than a threshold. The default and also minimal threshold is 8 IP, which means that only if the delegator’s reward is more than 8 IP, it will be sent to the delegator’s account.

The reward distribution will go to a reward distribution queue, which only processes a fixed amount of reward distribution requests per block. The reward distribution per block is 32.

The staking reward cannot be manually withdrawn by design.

Community Pool

A percentage of the newly minted tokens in every block will go to a community pool contract. The foundation will determine how to use the tokens sent to the pool. The maximum community pool percentage that can be set is 20%.

The community pool contract address: 0xcccccc0000000000000000000000000000000002

Singularity

The first 1,580,851 blocks after the genesis is called Singularity, during which everyone can create a validator and stake tokens but the active validator set will only have the genesis validators. There is also no new token emission, hence no reward. Unstake and redelegate are also not supported.

The Genesis validator set consists of 8 validators, setup by the foundation and trusted staking institutions. 4 of them support locked tokens and the other 4 support unlocked tokens. Each of them has an initial stake of 0.001 IP. Each of them will set a commission rate. During the Singularity, the genesis valdiators will need to self delegate at least 1024 IP to perform validator operations like editing validator commission rate.

After Singularity, the top 64 validator nodes with the highest stakes will be selected to participate in consensus and receive rewards.

Slashing/Jail won’t happen during Singularity.

Staking contract

Story’s staking contract will handle all validators/delegators related operations. It’s deployed to address: 0xcccccc0000000000000000000000000000000001

The contract interfaces are defined here: https://github.com/piplabs/story/blob/main/contracts/src/protocol/IPTokenStaking.sol