Staking
Arthera has a number of system contracts that perform various protocol-level tasks. The choice to decouple some functionality form the main blockchain node to system contract is related to upgradeability. All System Contracts are upgradeble through a governance process, so if a vote is cast through governance to change the price of subscription plans or staking rewards, a new version of the respective contracts will be deployed without having validators upgrade their software or restart their node.
This contract is responsible for:
- registering new validators and delegators
- withdrawal of validators and delegators
- distribution of epoch rewards
currentEpoch()
Returns uint256
- the current epoch
epochEndTime()
Returns uint256
- the end time epoch in epoch seconds
minSelfStake()
Returns uint256
- the minimum amount of stake for a validator
maxDelegatedRatio()
Returns uint256
- maximum ratio of delegations a validator can have
validatorCommission()
Returns uint256
- the commission fee in percentage a validator will get from a delegation
burntFeeShare()
Returns uint256
- the percentage of transaction fees to burn
treasuryFeeShare()
Returns uint256
- the percentage of fees to transfer to Arthera's treasury address
unlockedRewardRatio()
Returns uint256
- the ratio of the reward rate at base rate (no locking)
minLockupDuration()
Returns uint256
- the minimum duration of a stake/delegation lockup
maxLockupDuration()
Returns uint256
- the maximum duration of a stake/delegation lockup
withdrawalPeriodEpochs()
Returns uint256
- the number of epochs for stake to be available for withdrawal after an undelegation request
withdrawalPeriodTime()
Returns uint256
- the time it takes for stake to be available for withdrawal after an undelegation request
getEpochValidatorIDs()
Returns uint256[]
- the list of validator id's that were active in the provided epoch.
Method parameters:
uint256 epoch
the epoch
isSlashed()
Returns bool
- if the validator is currently slashed
Method parameters:
uint256 validatorID
the id of the validator
getEpochReceivedStake()
Returns uint256
the stake owned by a validator in an epoch
Method parameters:
uint256 epoch
the epochuint256 validatorID
the id of the validator
getEpochAccumulatedRewardPerToken()
Returns uint256
the reward generated by a validator for one staked token in an epoch
Method parameters:
uint256 epoch
the epochuint256 validatorID
the id of the validator
getEpochAccumulatedUptime()
Returns uint256
the total uptime for a validator in an epoch
Method parameters:
uint256 epoch
the epochuint256 validatorID
the id of the validator
getEpochOfflineTime()
Returns uint256
the total downtime for a validator in an epoch
Method parameters:
uint256 epoch
the epochuint256 validatorID
the id of the validator
getEpochOfflineBlocks()
Returns uint256
the total blocks missed by a downtime validator in an epoch
Method parameters:
uint256 epoch
the epochuint256 validatorID
the id of the validator
getEpochAccumulatedOriginatedTxsFee()
Returns uint256
total transaction fees collected by a validator in an epoch
Method parameters:
uint256 epoch
the epochuint256 validatorID
the id of the validator
getSelfStake()
Returns uint256
the validator's own stake, not including delegators
Method parameters:
uint256 validatorID
the id of the validator
getLockedStake()
Returns uint256
the amount of locked stake for a delegator in the provided validator
Method parameters:
address delegator
delegatoruint256 toValidatorID
the id of the validator
createValidator() payable
Create a new validator with a minimum stake given by minSelfStake()
. This method is payable
, so an AA value greater
than Staking.minSelfStake()
needs to be sent along with the transaction. The call creates a self-delegation with the specified amount.
The sender's address will be the validator's registered address in the Staking contract.
Method parameters:
msg.sender
- the validator addressbytes pubkey
is the validator's public key used to sign messages and cannot be changed after the validator is created.
Emits
event CreatedValidator(uint256 indexed validatorID, address indexed auth, uint256 createdEpoch, uint256 createdTime)
delegate() payable
Delegates an amount of AA to a validator. This method can be used to create a new delegation or increase an existing delegation.
The delegated stake is always unlocked unless locked explicitly with lockStake
. This method is payable
, so an AA value needs
to be sent with the transaction.
The maximum delegated value a validator can have is 16 * getSelfStake(validatorId)
. If your delegation will go over this value,
the transaction will be reverted with an error.
Method parameters:
msg.sender
- delegatoruint256 toValidatorId
is the validator's public key used to sign messages and cannot be changed after the validator is created.
Emits
event Delegated(address indexed delegator, uint256 indexed toValidatorID, uint256 amount)
undelegate()
Make a request to release an amount of delegated stake from a validator for withdrawal. The delegated stake will be released after the following both conditions are met:
block.timestamp >= undelegateRequestTime + Staking.withdrawalPeriodTime()
Staking.currentEpoch() >= undelegateRequestEpoch + Staking.withdrawalPeriodEpochs()
.
Once the delegated stake is release, withdraw()
can be called to retrieve the funds.
Method parameters:
msg.sender
- delegatoruint256 fromValidatorID
the ID of the validator.uint256 withdrawalRequestID
a number that uniquely identifies your request for internal reference. Note that you cannot make twoundelegate
requests with the samewithdrawalRequestID
. It can be anyuint256
number you want.uint256 amount
the amount inwei
you want to undelegate.
Emits
event Undelegated(address indexed delegator, uint256 indexed fromValidatorID, uint256 indexed withdrawalRequestID, uint256 amount)
withdraw()
Finalizes a withdrawal request. It clears the request object and transfers the requested amount to caller's address.
If validator was dishonest, the delegator's requested amount may be fully or partially slashed according to the validator's slashingRefundRatio
available
at Staking.slashingRefundRatio
Method parameters:
msg.sender
- delegator where the requested amount will be sentuint256 fromValidatorID
the ID of the validator.uint256 withdrawalRequestID
a number that uniquely identifies theundelegate
request, provided initially in theundelegate
method.
Emits
Withdrawn(address indexed delegator, uint256 indexed fromValidatorID, uint256 indexed withdrawalRequestID, uint256 amount)
lockStake()
Rewards for a locked stake are higher than rewards for non-locked stake. See Locking stake for more details. A validator's stake must be locked up before the validator's delegations can lock their sake and the specified lockup period of a delegation must not exceed the validator's current lockup period. Delegations can lock only a part of their stake.
A validator can lock his stake by sending the call from the validator's registered address in createValidator()
.
Method parameters:
msg.sender
- delegatoruint256 toValidatorID
- the validator where your delegation isuint256 lockupDuration
- the lockup duration in seconds ( >= 14 days and <= 365 days )uint256 amount
- an amount inwei
<= the delegator's stake
Emits
event LockedUpStake(address indexed delegator, uint256 indexed validatorID, uint256 duration, uint256 amount)
relockStake()
Extend the lockup period or increase the lock-up amount. The new lockup duration will not be extending the old duration, but set a new duration starting now and cannot be lower than the previous lockup duration.
Method parameters:
msg.sender
- delegatoruint256 toValidatorID
- the validator where your delegation isuint256 lockupDuration
- the now lockup duration in seconds ( >= 14 days and <= 365 days ), starting now. Cannot be lower than the previous lockup duration.uint256 amount
- an amount inwei
<= the delegator's stake that will be added to the existing locked amount
Emits
event LockedUpStake(address indexed delegator, uint256 indexed validatorID, uint256 duration, uint256 amount)
unlockStake()
Unlock the stake before the lockup duration is elapsed. Please note that a penalty will be applied to the unlocked amount. See Locking stake for more details.
Method parameters:
msg.sender
- delegatoruint256 toValidatorID
- the validator where your locked delegation isuint256 amount
- an amount inwei
to unlock
Emits
event UnlockedStake(address indexed delegator, uint256 indexed validatorID, uint256 amount, uint256 penalty)
pendingRewards()
Checks to see if there are any pending rewards to be claimed for a delegator.
Method parameters:
address delegator
- delegatoruint256 toValidatorID
- the validator where your delegation is
Returns uint256
the amount of pending rewards that can be claimed
claimRewards()
Claim pending rewards for a delegator.
Method parameters:
msg.sender
- delegator where the rewards in AA will be sentuint256 toValidatorID
- the validator where your delegation is
Emits
event ClaimedRewards(address indexed delegator, uint256 indexed toValidatorID, uint256 lockupExtraReward, uint256 lockupBaseReward, uint256 unlockedReward)
restakeRewards()
Re-stakes any pending rewards. The pending rewards will be added to the staked amount. If any part of pending rewards come from locked-up stake, the entire pending amount will be added to the locked stake.
Method parameters:
msg.sender
- delegatoruint256 toValidatorID
- the validator where your delegation is
Emits
event RestakedRewards(address indexed delegator, uint256 indexed toValidatorID, uint256 lockupExtraReward, uint256 lockupBaseReward, uint256 unlockedReward)