Staking ProtocolrewardsDistributionrateBasedRewardDistributionrateBasedLockRewardDistribution

RateBasedLockRewardDistributionFacetStorage

This library manages the storage and logic for the Rate-Based Lock Reward Distribution algorithm.

_Instant stake rewards are always supported by default. Rewards are calculated as the product of the respective reward rate (i.e., campaignRate), the lockPeriod (for instant stake rewards) and activePeriod (for claimable rewards), and the virtual balance of positions.

IMPORTANT:

  • Rate-Based Reward Distribution Facets should only be used in conjuction with RewardMinter Facets for configuring reward assets in staking campaigns.

  • This implementation is intended to be leveraged by campaigns where locking positions is a fundamental requirement for participation and instant staking rewards are featured. It does not cater to scenarios where stakeholders can freely unstake their positions at any time._

CampaignNotOnCreationStateForSetting

error CampaignNotOnCreationStateForSetting(uint256 campaignId)

Thrown when a targeted campaign is not "On Creation" state, which is required at configurations.

InvalidZeroCampaignRate

error InvalidZeroCampaignRate(uint256 campaignId)

Thrown when the campaign rate is set to 0, which is not allowed.

NotCampaignCreator

error NotCampaignCreator(uint256 campaignId, address unauthorizedAddress)

Thrown when an account not being the creator of a campaign attempts to change its reward rate.

STORAGE_SLOT

bytes32 STORAGE_SLOT

Unique identifier for the storage slot where the Layout struct is stored.

DIVIDER

uint256 DIVIDER

Used to normalize values (e.g., rates) for calculations with up to 18 decimal precision.

Layout

Struct for managing campaign information.

struct Layout {
  mapping(uint256 => struct RateBasedRewardLockDistributionFacetStorage.CampaignInfo) campaignInfoLocal;
}

CampaignInfo

Struct containing local information for a staking campaign.

struct CampaignInfo {
  uint256 currentIndex;
  bool isVirtualLockMultipliersSupported;
  mapping(uint256 => struct RateBasedRewardLockDistributionFacetStorage.NftInfo) nftInfoLocal;
  uint256[] campaignRates;
  uint256[] rateChangeSnapshots;
}

NftInfo

Struct containing local information for an NFT LP token associated with a staking position.

struct NftInfo {
  uint256 lastRewardTimestamp;
  uint256 currentNftRate;
}

layout

function layout() internal pure returns (struct RateBasedRewardLockDistributionFacetStorage.Layout l)

Retrieves a reference to the Layout struct stored at the slot specified by STORAGE_SLOT unique identifier.

setCampaignRewardsDistribution

function setCampaignRewardsDistribution(struct RateBasedRewardLockDistributionFacetStorage.Layout l, uint256 campaignId, bytes campaignRewardsDistributionData) internal returns (uint256, bool)

Sets the rewards distribution schedule (rate & optional lock multipliers feature) for a specified campaign.

This function can only be called during the campaign's creation (see CampaignCreationSkeleton.createCampaign()).

Parameters

NameTypeDescription
lstruct RateBasedRewardLockDistributionFacetStorage.LayoutA reference to the Layout struct in storage.
campaignIduint256The unique identifier of the targeted staking campaign.
campaignRewardsDistributionDatabytesThe ABI encoded data containing the reward rate and boolean flag for supporting lock multipliers.

changeCampaignRate

function changeCampaignRate(struct RateBasedRewardLockDistributionFacetStorage.Layout l, uint256 campaignId, uint256 newRate) internal

Changes the rate of rewards for a specified campaign.

Records the current block.timestamp when the change is applied. This function can only be called by the creator of the targeted campaign.

Parameters

NameTypeDescription
lstruct RateBasedRewardLockDistributionFacetStorage.LayoutA reference to the Layout struct in storage.
campaignIduint256The unique identifier of the targeted staking campaign.
newRateuint256The new reward rate to be applied for the campaign (must be scaled with 1e18).

applyStake

function applyStake(struct RateBasedRewardLockDistributionFacetStorage.Layout l, uint256 campaignId, uint256 nftId, uint256 virtualPacketsStaked, uint256 packetsStaked, address account) internal returns (uint256)

Creates a new staking position in the specified campaign.

Staking rewards (instant) are calculated based on the respective lock period and transferred to the position's creator. If lock multipliers are supported (isVirtualLockMultipliersSupported == true) then the associated lock multiplier (depends on periodLocked) is applied to the position. If no amount multiplier is applied, virtualPacketsStaked will be equal to packetsStaked.

Parameters

NameTypeDescription
lstruct RateBasedRewardLockDistributionFacetStorage.LayoutA reference to the Layout struct in storage.
campaignIduint256The unique identifier of the targeted staking campaign.
nftIduint256The unique identifier of the NFT associated with the position.
virtualPacketsStakeduint256The number of staked (input) packets adjusted by the applicable amount multiplier.
packetsStakeduint256The raw number of staked packets, without accounting for amount multipliers.
accountaddressThe address of the user creating and owning the position.

Return Values

NameTypeDescription
[0]uint256The insta stake reward packets

applyUnstake

function applyUnstake(struct RateBasedRewardLockDistributionFacetStorage.Layout l, uint256 campaignId, uint256 nftId) internal returns (uint256)

Returns the claimable rewards for a position being unstaked (either partially or fully).

The calculation is performed without accounting for lock multipliers, since unstake can only occur after lock has expired. See getReward() for details on reward calculation.

Parameters

NameTypeDescription
lstruct RateBasedRewardLockDistributionFacetStorage.LayoutA reference to the Layout struct in storage.
campaignIduint256The unique identifier of the targeted staking campaign.
nftIduint256The unique identifier of the NFT associated with the position.

Return Values

NameTypeDescription
[0]uint256The calculated claimable rewards.

getReward

function getReward(struct RateBasedRewardLockDistributionFacetStorage.Layout l, uint256 campaignId, uint256 nftId) internal returns (uint256)

Returns the claimable rewards for a specific position.

The claimable rewards are calculated without accounting for lock multipliers (see calculateRewardNoLock()).

Parameters

NameTypeDescription
lstruct RateBasedRewardLockDistributionFacetStorage.LayoutA reference to the Layout struct in storage.
campaignIduint256The unique identifier of the targeted staking campaign.
nftIduint256The unique identifier of the NFT associated with the position.

Return Values

NameTypeDescription
[0]uint256The rewards that can be claimed by the specified position.

calculateRewardVirtualLock

function calculateRewardVirtualLock(uint256 rateToBeUsed, uint256 nftId, uint256 totalPeriodLocked) internal view returns (uint256)

Calculates the instant stake rewards based on the specified reward rate, virtual balance, and total lock duration.

The calculation accounts for both the amount multiplier and lock multiplier applied to the position. The function assumes that the campaignRate input value is scaled by 1e18. Called by applyStake().

Parameters

NameTypeDescription
rateToBeUseduint256The reward rate to be used in the calculation (should be scaled by 1e18).
nftIduint256The unique identifier of the NFT associated with the position.
totalPeriodLockeduint256The duration (in seconds) that the position is locked.

Return Values

NameTypeDescription
[0]uint256The calculated instant stake rewards, scaled down by DIVIDER.

calculateRewardNoLock

function calculateRewardNoLock(struct RateBasedRewardLockDistributionFacetStorage.Layout l, uint256 campaignId, uint256 nftId) internal view returns (uint256)

Returns the calculated accrued rewards (without accounting for lock multipliers) that a position holds.

The position's total active period is calculated from the respective lastRewardTimestamp up to the current block.timestamp. If the reward rate has been updated since last rewards provision or during the position's lock cycle, then the total active period is divided into distinct periods corresponding to the different rates involved.

Parameters

NameTypeDescription
lstruct RateBasedRewardLockDistributionFacetStorage.LayoutA reference to the Layout struct in storage.
campaignIduint256The unique identifier of the targeted staking campaign.
nftIduint256The unique identifier of the NFT associated with the position.

Return Values

NameTypeDescription
[0]uint256The calculated accrued rewards.

_calculateRewardNoLock

function _calculateRewardNoLock(uint256 campaignRate, uint256 virtualPacketBalance, uint256 activePeriod) internal pure returns (uint256)

Calculates rewards based on the specified reward rate, virtual balance, and active duration.

This function assumes that the virtual packet balance only accounts for the amount multiplier and does not consider any lock multipliers. It also assumes that the campaignRate input value is scaled by 1e18.

Parameters

NameTypeDescription
campaignRateuint256The reward rate to use (should be scaled by 1e18).
virtualPacketBalanceuint256The virtual balance, considering only the amount multiplier.
activePerioduint256The duration for which the reward is calculated, expressed in seconds.

Return Values

NameTypeDescription
[0]uint256The calculated reward for the specified parameters, scaled down by DIVIDER.

snapshotsTimestampLookup

function snapshotsTimestampLookup(uint256[] snapshots, uint256 targetTimestamp) internal pure returns (uint256)

Looks up a target timestamp in a list of sorted (ascending order) timestamps using Binary Search.

It returns the index of the array's element that is either equal to the target or the closest one less than the target. Called by calculateRewardNoLock().

Parameters

NameTypeDescription
snapshotsuint256[]The array containing the sorted timestamps (in ascending order).
targetTimestampuint256The timestamp to search for in the array.

Return Values

NameTypeDescription
[0]uint256The index of the element that is equal to or the closest less than the target.