# Staking
# Overview
The Staking contract hold and track the changes of all staked SQT Token, It provides entry for the indexers and delegators to stake/unstake, delegate/undelegate to available Indexers and withdraw their SQT Token. It also track the changes of the commission rate of each Indexer and make these changes always applied at two Eras later. We design this to allow time for the delegators to consider their delegation when an Indxer changes the commission rate.
# Terminology
stake -- Indexers must stake SQT Token to themself and not less than the minimumStakingAmount we set in IndexerRegistry contract delegate -- Delegators can delegate SQT Token to any indexer to share Indexer‘s Rewards. total staked amount -- indexer's stake amount + total delegate amount. The Indexer staked amount effects its max acceptable delegation amount. The total staked amount of an Indexer effects the maximum reward it can earn in an Era.
# Detail
Since The change of stake or delegate amount and commission rate affects the rewards distribution. So when users make these changes, we call onStakeChange()/onICRChnage() from rewardsStaking/rewardsPool contract to notify it to apply these changes for future distribution. In our design rewardsStaking contract apply the first stake change and commission rate change immediately when an Indexer make registration. Later on all the stake change apply at next Era, commission rate apply at two Eras later.
Since Indexers need to stake SQT Token at registration and the staked amount effects its max acceptable delegation amount. So the implementation of stake() is diffrernt with delegate().
- stake() is for Indexers to stake on themself. There has no stake amount limitation.
- delegate() is for delegators to delegate on an indexer and need to consider the indexer's delegation limitation.
Also in this contarct we has two entries to set commission rate for indexers. setInitialCommissionRate() is called by IndexrRegister contract when indexer register, this change need to take effect immediately. setCommissionRate() is called by Indexers to set their commission rate, and will be take effect after two Eras.
Since Indexer must keep the minimumStakingAmount, so the implementation of unstake() also different with undelegate().
- unstake() is for Indexers to unstake their staking token. An indexer can not unstake all the token unless the indexer unregister from the network. Indexer need to keep the minimumStakingAmount staked on itself when it unstake.
- undelegate() is for delegator to undelegate from an Indexer can be called by Delegators. Delegators can undelegate all their delegated tokens at one time. Tokens will transfer to user's account after the lockPeriod when users apply withdraw. Every widthdraw will cost a fix rate fees(unbondFeeRate), and these fees will be burned.
# settings
contract ISettings settings
# indexerLeverageLimit
The ratio of total stake amount to indexer self stake amount to limit the total delegation amount. Initial value is set to 10, which means the total stake amount cannot exceed 10 times the indexer self stake amount.
uint256 indexerLeverageLimit
# unbondFeeRate
uint256 unbondFeeRate
# lockPeriod
uint256 lockPeriod
# indexerLength
uint256 indexerLength
# maxUnbondingRequest
uint256 maxUnbondingRequest
# indexers
mapping(uint256 => address) indexers
# indexerNo
mapping(address => uint256) indexerNo
# totalStakingAmount
mapping(address => struct StakingAmount) totalStakingAmount
# unbondingAmount
mapping(address => mapping(uint256 => struct UnbondAmount)) unbondingAmount
# unbondingLength
mapping(address => uint256) unbondingLength
# withdrawnLength
mapping(address => uint256) withdrawnLength
# delegation
mapping(address => mapping(address => struct StakingAmount)) delegation
# lockedAmount
mapping(address => uint256) lockedAmount
# stakingIndexers
mapping(address => mapping(uint256 => address)) stakingIndexers
# stakingIndexerNos
mapping(address => mapping(address => uint256)) stakingIndexerNos
# stakingIndexerLengths
mapping(address => uint256) stakingIndexerLengths
Emitted when stake to an Indexer.
# DelegationAdded
event DelegationAdded(address source, address indexer, uint256 amount)
Emitted when unstake to an Indexer.
# DelegationRemoved
event DelegationRemoved(address source, address indexer, uint256 amount)
Emitted when request unbond.
# UnbondRequested
event UnbondRequested(address source, address indexer, uint256 amount, uint256 index, enum UnbondType _type)
Emitted when request withdraw.
# UnbondWithdrawn
event UnbondWithdrawn(address source, uint256 amount, uint256 fee, uint256 index)
Emitted when delegtor cancel unbond request.
# UnbondCancelled
event UnbondCancelled(address source, address indexer, uint256 amount, uint256 index)
# onlyStakingManager
modifier onlyStakingManager()
Initialize this contract.
# initialize
function initialize(contract ISettings _settings, uint256 _lockPeriod, uint256 _unbondFeeRate) external
# setSettings
function setSettings(contract ISettings _settings) external
# setLockPeriod
function setLockPeriod(uint256 _lockPeriod) external
# setIndexerLeverageLimit
function setIndexerLeverageLimit(uint256 _indexerLeverageLimit) external
# setUnbondFeeRateBP
function setUnbondFeeRateBP(uint256 _unbondFeeRate) external
# setMaxUnbondingRequest
function setMaxUnbondingRequest(uint256 maxNum) external
when Era update if valueAfter is the effective value, swap it to valueAt, so later on we can update valueAfter without change current value require it idempotent.
# reflectEraUpdate
function reflectEraUpdate(address _source, address _indexer) public
# _reflectStakingAmount
function _reflectStakingAmount(uint256 eraNumber, struct StakingAmount stakeAmount) private
# checkDelegateLimitation
function checkDelegateLimitation(address _indexer, uint256 _amount) external view
# addIndexer
function addIndexer(address _indexer) external
# removeIndexer
function removeIndexer(address _indexer) external
# removeUnbondingAmount
function removeUnbondingAmount(address _source, uint256 _unbondReqId) external
# addDelegation
function addDelegation(address _source, address _indexer, uint256 _amount) external
# delegateToIndexer
function delegateToIndexer(address _source, address _indexer, uint256 _amount) external
# removeDelegation
function removeDelegation(address _source, address _indexer, uint256 _amount) external
When the delegation change nodify rewardsStaking to deal with the change.
# _onDelegationChange
function _onDelegationChange(address _source, address _indexer) internal
# startUnbond
function startUnbond(address _source, address _indexer, uint256 _amount, enum UnbondType _type) external
Withdraw a single request. burn the withdrawn fees and transfer the rest to delegator.
# withdrawARequest
function withdrawARequest(address _source, uint256 _index) external
# slashIndexer
function slashIndexer(address _indexer, uint256 _amount) external
# unbondCommission
function unbondCommission(address _indexer, uint256 _amount) external
# isEmptyDelegation
function isEmptyDelegation(address _source, address _indexer) external view returns (bool)