View Source: contracts/governance/StakingRewards/StakingRewards.sol
↗ Extends: StakingRewardsStorage
This is a trial incentive program. In this, the SOV emitted and becoming liquid from the Adoption Fund could be utilized to offset the higher APY's offered for Liquidity Mining events. Vesting contract stakes are excluded from these rewards. Only wallets which have staked previously liquid SOV are eligible for these rewards. Tokenholders who stake their SOV receive staking rewards, a pro-rata share of the revenue that the platform generates from various transaction fees plus revenues from stakers who have a portion of their SOV slashed for early unstaking.
Events
event RewardWithdrawn(address indexed receiver, uint256 amount);
- initialize(address _SOV, IStaking _staking)
- stop()
- collectReward(uint256 restartTime)
- withdrawTokensByOwner(address _receiverAddress)
- setAverageBlockTime(uint256 _averageBlockTime)
- setBlock()
- setHistoricalBlock(uint256 _time)
- setMaxDuration(uint256 _duration)
- _computeRewardForDate(address _staker, uint256 _block, uint256 _date)
- _payReward(address _staker, uint256 amount)
- _transferSOV(address _receiver, uint256 _amount)
- _getCurrentBlockNumber()
- _setBlock(uint256 _checkpointTime)
- getStakerCurrentReward(bool considerMaxDuration, uint256 restartTime)
Replacement of constructor by initialize function for Upgradable Contracts This function will be called only once by the owner.
function initialize(address _SOV, IStaking _staking) external nonpayable onlyOwner
Arguments
Name | Type | Description |
---|---|---|
_SOV | address | SOV token address |
_staking | IStaking | StakingProxy address should be passed |
Source Code
function initialize(address _SOV, IStaking _staking) external onlyOwner {
require(_SOV != address(0), "Invalid SOV Address.");
require(Address.isContract(_SOV), "_SOV not a contract");
SOV = IERC20(_SOV);
staking = _staking;
startTime = staking.timestampToLockDate(block.timestamp);
setMaxDuration(15 * TWO_WEEKS);
deploymentBlock = _getCurrentBlockNumber();
}
Stops the current rewards program.
function stop() external nonpayable onlyOwner
Source Code
function stop() external onlyOwner {
require(stopBlock == 0, "Already stopped");
stopBlock = _getCurrentBlockNumber();
}
Collect rewards
function collectReward(uint256 restartTime) external nonpayable
Arguments
Name | Type | Description |
---|---|---|
restartTime | uint256 | The time from which the staking rewards calculation shall restart. The issue is that we can only run for a max duration and if someone stakes for the first time after the max duration is over, the reward will always return 0. Thus, we need to restart from the duration that elapsed without generating rewards. |
Source Code
function collectReward(uint256 restartTime) external {
(uint256 withdrawalTime, uint256 amount) = getStakerCurrentReward(true, restartTime);
require(withdrawalTime > 0 && amount > 0, "no valid reward");
withdrawals[msg.sender] = withdrawalTime;
_payReward(msg.sender, amount);
}
Withdraws all token from the contract by Multisig.
function withdrawTokensByOwner(address _receiverAddress) external nonpayable onlyOwner
Arguments
Name | Type | Description |
---|---|---|
_receiverAddress | address | The address where the tokens has to be transferred. |
Source Code
function withdrawTokensByOwner(address _receiverAddress) external onlyOwner {
uint256 value = SOV.balanceOf(address(this));
_transferSOV(_receiverAddress, value);
}
Changes average block time - based on blockchain
function setAverageBlockTime(uint256 _averageBlockTime) external nonpayable onlyOwner
Arguments
Name | Type | Description |
---|---|---|
_averageBlockTime | uint256 |
Source Code
function setAverageBlockTime(uint256 _averageBlockTime) external onlyOwner {
averageBlockTime = _averageBlockTime;
}
This function computes the last staking checkpoint and calculates the corresponding
block number using the average block time which is then added to the mapping checkpointBlockDetails
.
function setBlock() external nonpayable
Source Code
function setBlock() external {
uint256 lastCheckpointTime = staking.timestampToLockDate(block.timestamp);
_setBlock(lastCheckpointTime);
}
This function computes the block number using the average block time for a given historical
checkpoint which is added to the mapping checkpointBlockDetails
.
function setHistoricalBlock(uint256 _time) external nonpayable
Arguments
Name | Type | Description |
---|---|---|
_time | uint256 | Exact staking checkpoint time |
Source Code
function setHistoricalBlock(uint256 _time) external {
_setBlock(_time);
}
Sets the max duration
function setMaxDuration(uint256 _duration) public nonpayable onlyOwner
Arguments
Name | Type | Description |
---|---|---|
_duration | uint256 | Max duration for which rewards can be collected at a go (in seconds) |
Source Code
function setMaxDuration(uint256 _duration) public onlyOwner {
maxDuration = _duration;
}
Internal function to calculate weighted stake
function _computeRewardForDate(address _staker, uint256 _block, uint256 _date) internal view
returns(weightedStake uint256)
Arguments
Name | Type | Description |
---|---|---|
_staker | address | Staker address |
_block | uint256 | Last finalised block |
_date | uint256 | The date to compute prior weighted stakes |
Returns
The weighted stake
Source Code
function _computeRewardForDate(
address _staker,
uint256 _block,
uint256 _date
) internal view returns (uint256 weightedStake) {
weightedStake = staking.getPriorWeightedStake(_staker, _block, _date);
if (stopBlock > 0 && stopBlock < _block) {
uint256 previousWeightedStake =
staking.getPriorWeightedStake(_staker, stopBlock, _date);
if (previousWeightedStake < weightedStake) {
weightedStake = previousWeightedStake;
}
}
}
Internal function to pay rewards
function _payReward(address _staker, uint256 amount) internal nonpayable
Arguments
Name | Type | Description |
---|---|---|
_staker | address | User address |
amount | uint256 | the reward amount |
Source Code
function _payReward(address _staker, uint256 amount) internal {
require(SOV.balanceOf(address(this)) >= amount, "not enough funds to reward user");
claimedBalances[_staker] = claimedBalances[_staker].add(amount);
_transferSOV(_staker, amount);
}
transfers SOV tokens to given address
function _transferSOV(address _receiver, uint256 _amount) internal nonpayable
Arguments
Name | Type | Description |
---|---|---|
_receiver | address | the address of the SOV receiver |
_amount | uint256 | the amount to be transferred |
Source Code
function _transferSOV(address _receiver, uint256 _amount) internal {
require(_amount != 0, "amount invalid");
require(SOV.transfer(_receiver, _amount), "transfer failed");
emit RewardWithdrawn(_receiver, _amount);
}
Determine the current Block Number
function _getCurrentBlockNumber() internal view
returns(uint256)
Source Code
function _getCurrentBlockNumber() internal view returns (uint256) {
return block.number;
}
Internal function to calculate and set block
function _setBlock(uint256 _checkpointTime) internal nonpayable
Arguments
Name | Type | Description |
---|---|---|
_checkpointTime | uint256 |
Source Code
function _setBlock(uint256 _checkpointTime) internal {
uint256 currentTS = block.timestamp;
uint256 lastFinalisedBlock = _getCurrentBlockNumber() - 1;
require(checkpointBlockDetails[_checkpointTime] == 0, "block number already set");
uint256 checkpointBlock =
lastFinalisedBlock.sub(((currentTS.sub(_checkpointTime)).div(averageBlockTime)));
checkpointBlockDetails[_checkpointTime] = checkpointBlock;
}
Get staker's current accumulated reward
function getStakerCurrentReward(bool considerMaxDuration, uint256 restartTime) public view
returns(lastWithdrawalInterval uint256, amount uint256)
Arguments
Name | Type | Description |
---|---|---|
considerMaxDuration | bool | True: Runs for the maximum duration - used in tx not to run out of gas False - to query total rewards |
restartTime | uint256 | The time from which the staking rewards calculation shall restart. |
Returns
The timestamp of last withdrawal
Source Code
function getStakerCurrentReward(bool considerMaxDuration, uint256 restartTime)
public
view
returns (uint256 lastWithdrawalInterval, uint256 amount)
{
uint256 weightedStake;
uint256 lastFinalisedBlock = _getCurrentBlockNumber() - 1;
uint256 currentTS = block.timestamp;
uint256 duration;
address staker = msg.sender;
uint256 lastWithdrawal = withdrawals[staker];
uint256 lastStakingInterval = staking.timestampToLockDate(currentTS);
lastWithdrawalInterval = lastWithdrawal > 0 ? lastWithdrawal : startTime;
if (lastStakingInterval <= lastWithdrawalInterval) return (0, 0);
/* Normally the restart time is 0. If this function returns a valid lastWithdrawalInterval
and zero amount - that means there were no valid rewards for that period. So the new period must start
from the end of the last interval or till the time no rewards are accumulated i.e. restartTime */
if (restartTime >= lastWithdrawalInterval) {
uint256 latestRestartTime = staking.timestampToLockDate(restartTime);
lastWithdrawalInterval = latestRestartTime;
}
if (considerMaxDuration) {
uint256 addedMaxDuration = lastWithdrawalInterval.add(maxDuration);
duration = addedMaxDuration < currentTS
? staking.timestampToLockDate(addedMaxDuration)
: lastStakingInterval;
} else {
duration = lastStakingInterval;
}
for (uint256 i = lastWithdrawalInterval; i < duration; i += TWO_WEEKS) {
uint256 referenceBlock = checkpointBlockDetails[i];
if (referenceBlock == 0) {
referenceBlock = lastFinalisedBlock.sub(
((currentTS.sub(i)).div(averageBlockTime))
);
}
if (referenceBlock < deploymentBlock) referenceBlock = deploymentBlock;
weightedStake = weightedStake.add(_computeRewardForDate(staker, referenceBlock, i));
}
lastWithdrawalInterval = duration;
amount = weightedStake.mul(BASE_RATE).div(DIVISOR);
}
- Address
- Administered
- AdminRole
- AdvancedToken
- AdvancedTokenStorage
- Affiliates
- AffiliatesEvents
- ApprovalReceiver
- BProPriceFeed
- CheckpointsShared
- Constants
- Context
- DevelopmentFund
- DummyContract
- EnumerableAddressSet
- EnumerableBytes32Set
- EnumerableBytes4Set
- ERC20
- ERC20Detailed
- ErrorDecoder
- Escrow
- EscrowReward
- FeedsLike
- FeesEvents
- FeeSharingCollector
- FeeSharingCollectorProxy
- FeeSharingCollectorStorage
- FeesHelper
- FourYearVesting
- FourYearVestingFactory
- FourYearVestingLogic
- FourYearVestingStorage
- GenericTokenSender
- GovernorAlpha
- GovernorVault
- IApproveAndCall
- IChai
- IContractRegistry
- IConverterAMM
- IERC1820Registry
- IERC20_
- IERC20
- IERC777
- IERC777Recipient
- IERC777Sender
- IFeeSharingCollector
- IFourYearVesting
- IFourYearVestingFactory
- IFunctionsList
- ILiquidityMining
- ILiquidityPoolV1Converter
- ILoanPool
- ILoanToken
- ILoanTokenLogicBeacon
- ILoanTokenLogicModules
- ILoanTokenLogicProxy
- ILoanTokenModules
- ILoanTokenWRBTC
- ILockedSOV
- IMoCState
- IModulesProxyRegistry
- Initializable
- InterestUser
- IPot
- IPriceFeeds
- IPriceFeedsExt
- IProtocol
- IRSKOracle
- ISovryn
- ISovrynSwapNetwork
- IStaking
- ISwapsImpl
- ITeamVesting
- ITimelock
- IV1PoolOracle
- IVesting
- IVestingFactory
- IVestingRegistry
- IWrbtc
- IWrbtcERC20
- LenderInterestStruct
- LiquidationHelper
- LiquidityMining
- LiquidityMiningConfigToken
- LiquidityMiningProxy
- LiquidityMiningStorage
- LoanClosingsEvents
- LoanClosingsLiquidation
- LoanClosingsRollover
- LoanClosingsShared
- LoanClosingsWith
- LoanClosingsWithoutInvariantCheck
- LoanInterestStruct
- LoanMaintenance
- LoanMaintenanceEvents
- LoanOpenings
- LoanOpeningsEvents
- LoanParamsStruct
- LoanSettings
- LoanSettingsEvents
- LoanStruct
- LoanToken
- LoanTokenBase
- LoanTokenLogicBeacon
- LoanTokenLogicLM
- LoanTokenLogicProxy
- LoanTokenLogicStandard
- LoanTokenLogicStorage
- LoanTokenLogicWrbtc
- LoanTokenSettingsLowerAdmin
- LockedSOV
- MarginTradeStructHelpers
- Medianizer
- ModuleCommonFunctionalities
- ModulesCommonEvents
- ModulesProxy
- ModulesProxyRegistry
- MultiSigKeyHolders
- MultiSigWallet
- Mutex
- Objects
- OrderStruct
- OrigingVestingCreator
- OriginInvestorsClaim
- Ownable
- Pausable
- PausableOz
- PreviousLoanToken
- PreviousLoanTokenSettingsLowerAdmin
- PriceFeedRSKOracle
- PriceFeeds
- PriceFeedsLocal
- PriceFeedsMoC
- PriceFeedV1PoolOracle
- ProtocolAffiliatesInterface
- ProtocolLike
- ProtocolSettings
- ProtocolSettingsEvents
- ProtocolSettingsLike
- ProtocolSwapExternalInterface
- ProtocolTokenUser
- Proxy
- ProxyOwnable
- ReentrancyGuard
- RewardHelper
- RSKAddrValidator
- SafeERC20
- SafeMath
- SafeMath96
- setGet
- SharedReentrancyGuard
- SignedSafeMath
- SOV
- sovrynProtocol
- StakingAdminModule
- StakingGovernanceModule
- StakingInterface
- StakingProxy
- StakingRewards
- StakingRewardsProxy
- StakingRewardsStorage
- StakingShared
- StakingStakeModule
- StakingStorageModule
- StakingStorageShared
- StakingVestingModule
- StakingWithdrawModule
- State
- SwapsEvents
- SwapsExternal
- SwapsImplLocal
- SwapsImplSovrynSwap
- SwapsUser
- TeamVesting
- Timelock
- TimelockHarness
- TimelockInterface
- TokenSender
- UpgradableProxy
- USDTPriceFeed
- Utils
- VaultController
- Vesting
- VestingCreator
- VestingFactory
- VestingLogic
- VestingRegistry
- VestingRegistry2
- VestingRegistry3
- VestingRegistryLogic
- VestingRegistryProxy
- VestingRegistryStorage
- VestingStorage
- WeightedStakingModule
- WRBTC