# RewardsDistributer
# Overview
The Rewards distributer contract tracks and distriubtes the rewards Era by Era. In each distribution, Indexers can take the commission part of rewards, the remaining rewards are distributed according to the staking amount of indexers and delegators.
# Terminology
Era -- Era is the period of reward distribution. In our design, we must distribute the rewards of the previous Era before we can move to the next Era. Commission Rate -- Commission Rates are set by Indexers, it is the proportion to be taken by the indexer in each reward distribution. Rewards -- Rewards are paid by comsumer for the service agreements with indexer. All the rewards are temporary hold by RewardsDistributer contract and distribute to Indexers and Delegator Era by Era.
# Detail
In the design of rewards distribution, we have added a trade-off mechanism for Indexer and Delegator to achieve a win-win situation. The more SQT token staked on an indexer, the higher limitation of ongoing agreements the indexer can have. In order to earn more rewards with extra agreements, Indexers can stake more to themself, or attract delegators delegate to them, and delegators can share the rewards base on their delegation. This distribution strategy ensures the quality of service and makes both indexers and delegators profitable.
We apply delegation amount changes at next era and commission rate changes are 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. But the first stake change and commission rate change of an indexer that made on registration are applied immediately, In this way, the rewards on the era that indexer registered can also be distributed correctly.
After the service agreements generated from PlanManager and PurchaseOfferMarket, the rewards paied by consumer are temporary hold by RewardsDistributer contract. RewardsDistributer first linearly split these rewards into Eras according to the era period and the period of the agreement. The distribution information are stored in eraRewardAddTable and eraRewardRemoveTable. In the specific distribution process, we calculate the rewards need to be distributed according to eraRewardAddTable and eraRewardRemoveTable, and distribute to Indexers and Delegators according to their stake amount at that time. Indexer's commission part of the rewards will transfer to indexer immediately after each distribution. And Indexer and delegator can claim accumulated rewards by call claim() any time.
# RewardInfo
struct RewardInfo {
uint256 accSQTPerStake;
mapping(address => uint256) rewardDebt;
uint256 lastClaimEra;
uint256 eraReward;
mapping(uint256 => uint256) eraRewardAddTable;
mapping(uint256 => uint256) eraRewardRemoveTable;
}
# STATES
# settings
ISettings contract which stores SubQuery network contracts address
contract ISettings settings
# info
Reward information: indexer => RewardInfo
mapping(address => struct RewardsDistributer.RewardInfo) info
# EVENTS
# DistributeRewards
Emitted when rewards are distributed for the earliest pending distributed Era.
event DistributeRewards(address indexer, uint256 eraIdx, uint256 rewards, uint256 commission)
# ClaimRewards
Emitted when user claimed rewards.
event ClaimRewards(address indexer, address delegator, uint256 rewards)
# RewardsChanged
Emitted when the rewards change, such as when rewards coming from new agreement.
event RewardsChanged(address indexer, uint256 eraIdx, uint256 additions, uint256 removals)
# onlyRewardsStaking
modifier onlyRewardsStaking()
FUNCTIONS
# initialize
Initialize this contract.
function initialize(contract ISettings _settings) external
# setSettings
function setSettings(contract ISettings _settings) external
# setLastClaimEra
Initialize the indexer first last claim era. Only RewardsStaking can call.
function setLastClaimEra(address indexer, uint256 era) external
Name | Type | Description |
---|---|---|
indexer | address | address |
era | uint256 | uint256 |
# setRewardDebt
Update delegator debt in rewards. Only RewardsStaking can call.
function setRewardDebt(address indexer, address delegator, uint256 amount) external
Name | Type | Description |
---|---|---|
indexer | address | address |
delegator | address | address |
amount | uint256 | uint256 |
# resetEraReward
Reset era reward. Only RewardsStaking can call.
function resetEraReward(address indexer, uint256 era) external
Name | Type | Description |
---|---|---|
indexer | address | address |
era | uint256 | uint256 |
# increaseAgreementRewards
Split rewards from agreemrnt into Eras: Rewards split into one era; Rewards split into two eras; Rewards split into more then two eras handled by splitEraSpanMore; Use eraRewardAddTable and eraRewardRemoveTable to store and track reward split info at RewardInfo. Only be called by ServiceAgreementRegistry contract when new agreement accepted.
function increaseAgreementRewards(uint256 agreementId) external
Name | Type | Description |
---|---|---|
agreementId | uint256 | agreement Id |
# addInstantRewards
Send rewards directly to the specified era. Maybe RewardsPool call or others contracts.
function addInstantRewards(address indexer, address sender, uint256 amount, uint256 era) external
Name | Type | Description |
---|---|---|
indexer | address | address |
sender | address | address |
amount | uint256 | uint256 |
era | uint256 | uint256 |
# collectAndDistributeRewards
check if the current Era is claimed.
function collectAndDistributeRewards(address indexer) public
# collectAndDistributeEraRewards
Calculate and distribute the rewards for the next Era of the lastClaimEra. Calculate by eraRewardAddTable and eraRewardRemoveTable. Distribute by distributeRewards method.
function collectAndDistributeEraRewards(uint256 currentEra, address indexer) public returns (uint256)
# claim
Claim rewards of msg.sender for specific indexer.
function claim(address indexer) public
# claimFrom
Claculate the Rewards for user and tranfrer token to user.
function claimFrom(address indexer, address user) public returns (uint256)
# _emitRewardsChangedEvent
extract for reuse emit RewardsChanged event
function _emitRewardsChangedEvent(address indexer, uint256 eraNumber, struct RewardsDistributer.RewardInfo rewardInfo) private
# _getCurrentEra
Get current Era number from EraManager.
function _getCurrentEra() private returns (uint256)
# userRewards
function userRewards(address indexer, address user) public view returns (uint256)
# getRewardInfo
function getRewardInfo(address indexer) public view returns (struct IndexerRewardInfo)
# getRewardAddTable
function getRewardAddTable(address indexer, uint256 era) public view returns (uint256)
# getRewardRemoveTable
function getRewardRemoveTable(address indexer, uint256 era) public view returns (uint256)
# getRewardDebt
function getRewardDebt(address indexer, address user) public view returns (uint256)