# 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)