Skip to main content

Staking Manager

To ensure Proof of Security consensus, Shibarium executes all proof verification and staking operations on the Ethereum smart contract, leaving the computation-heavy tasks to L2.

Stakeholders can take on the role of a validator, delegator, or watcher for reporting fraud. StakeManager is the primary contract for validator-related activities such as stake management, reward distribution, and signature verification. Only one role, either validator or delegator, can be assigned to a single Ethereum address as a design choice.

Using NFT ID as the source of ownership ensures that changes in ownership and signer will not impact the system.

validatorThreshold: Shows the maximum number of validators accepted by the system, also called slots.

AccountStateRoot

  • For various accounting done on Heimdall for validators and delegator, account root is submitted while submitting the checkpoint.
  • accRoot is used while claimRewards and unStakeClaim.

Stake/stakeFor

function stake( 
uint256 amount,
uint256 heimdallFee,
bool acceptDelegation,
bytes calldata signerPubkey
) public;

function stakeFor(
address user,
uint256 amount,
uint256 heimdallFee,
bool acceptDelegation,
bytes memory signerPubkey
) public;
  • Allows anyone with an amount (in BONE tokens) greater minDeposit than if currentValidatorSetSize is less than validatorThreshold .
  • MUST transfer amount+heimdallFee , puts validator into auction period for an auctionInterval.
  • updateTimeLine updates the special timeline data structure, which keeps track of active validators and active staking for a given epoch/checkpoint count.
  • One unique NFT is minted on each new stake/stakeFor call, which can be transferred to anyone but can be owned 1:1 Ethereum address.
  • acceptDelegation set true if validators want to accept delegation, ValidatorShare contract is deployed for the validator.

unstake

  1. If a validator decides to unstake, they will be removed from the validator set in the next epoch. However, this removal is only applicable to the current checkpoint.
  2. To account for a validator's exit, their stake will be removed from the timeline data structure, and the count for their exit epoch will be updated.
  3. If a validator had a delegation, they should collect all rewards before their exit, and their delegation contract should be locked to prevent new delegations.

unstakeClaim

function unstakeClaim(uint256 validatorId) public;
  • After unstaking validators are put into a withdrawal period so that they can be slashed if any fraud is found after unstaking for past frauds.
  • Once the WITHDRAWAL_DELAY period is served, validators can call this function and do settlement with stakeManager(get rewards if any, get staked tokens back, burn NFT etc)

Restake

function restake(uint256 validatorId, uint256 amount, bool stakeRewards) public;
  • Allows validators to increase their stake by putting new amount or rewards or both.
  • MUST update timeline(amount) for active stake.

withdrawRewards

function withdrawRewards(uint256 validatorId) public;
  • Allows validators to withdraw accumulated rewards, must consider getting rewards from delegation contract if validator accepts delegation.

updateSigner

function updateSigner(uint256 validatorId, bytes memory signerPubkey) public
  • Allows validators to update signer address(which is used to validate blocks on Shibarium chain and checkpoint sigs on stakeManager)

topUpForFee

function topUpForFee(uint256 validatorId, uint256 heimdallFee) public
  • Validators can top-up their balance for Heimdall fee.

claimFee

function claimFee( uint256 validatorId, uint256 accumSlashedAmount, uint256 accumFeeAmount, uint256 index, bytes memory proof ) public
  • Used to withdraw fee from Heimdall.
  • accountStateRoot is updated on each checkpoint, so that validators can provide proof of inclusion in this root for account on Heimdall and withdraw fee.
  • Note that accountStateRoot is re-written to prevent exits on multiple checkpoints(for old root and save accounting on stakeManager)
  • accumSlashedAmount is unused atm, will be used for slashing on Heimdall if needed.

StakingNFT

  • Standard ERC721 with few restrictions like one token per user and minted sequentially.

Validator Replacement

  • In order to replace poor-performing validators, there is a periodic auction for each validator slot.

  • For individual validators, there is an auction window where wanna-be validators can bid their amount and start an auction using startAuction function.

  • Once the auctionInterval is over, the last bidder needs to close the auction in order to confirm and become a validator. For this, they need to call confirmAuctionBid which accepts and behaves similarly to new the stake function for the upcoming validator and unStake for the old validator.

  • The current validator can bid for herself and try to keep that place.

  • The whole mech dynamically balances the stake value and overall security according to market conditions and the use of the Shibarium chain.

    startAuction

    function startAuction( uint256 validatorId, /** auction for validator */ uint256 amount /** amount greater then old validator's stake */ ) external;
    • In order to start a bid or bid higher on an already running auction this function is used.

    • The auction period runs in cycles like (auctionPeriod--dynasty)--(auctionPeriod--dynasty)--(auctionPeriod--dynasty) so it MUST check for the correct auction period.

    • perceivedStakeFactor is used to calculate the exact factor*old stake (note currently it is by default 1 WIP for picking the function).

    • MUST check for an auction from the last auction period if any still going on (one can choose to not call confirmAuction in order to get her capital out in the next auction).

    • Normally continuous english auction is going on in a auctionPeriod .

      confirmAuctionBid

      function confirmAuctionBid( uint256 validatorId, uint256 heimdallFee, /** for new validator */ bool acceptDelegation, bytes calldata signerPubkey ) external
    • MUST check that this is not an auctionPeriod.

    • If the last bidder is the owner of validatorId, the behavior should be similar to restake.

    • In the second case unStake validatorId and add new user as validator from next checkpoint, for the new user behavior should be similar to stake/stakeFor.

checkSignatures

function checkSignatures( uint256 blockInterval, bytes32 voteHash, bytes32 stateRoot, bytes memory sigs ) public
  • Writes are meant only for the RootChain contract when submitting checkpoints
  • voteHash on which all validators sign (BFT ⅔+1 agreement)
  • This function validates only unique sigs and checks for ⅔+1 power has signed on checkpoint root (inclusion in voteHash verification in RootChain contract for all data) currentValidatorSetTotalStake provides the current active stake.
  • Rewards are distributed proportionally to validators' stake.

isValidator

  • Checks if a given validator is active for the current epoch.

Timeline data structure

struct State { int256 amount; int256 stakerCount; }mapping(uint256 => State) public validatorState;

StakingInfo

Source: StakingInfo.sol

Centralized logging contract for both validator and delegation events, Includes a few read-only functions.

ValidatorShareFactory

Factory contract to deploy ValidatorShare contract for each validator who opt-in for delegation.

note

jail, unJail and slash function aren't used currently (part of slashing implementation).

Some of the information found on this page has been developed using the open-source information provided by Polygon.