StakingSkeleton
This facet is a core component (skeleton) of a staking platform, enabling users to participate in existing staking campaigns and manage their staked positions represented by NFTs.
_Each user position is represented by an ERC721 NFT staking position token, minted upon successfully staking. Each position is uniquely tied to a specific campaign and governed by its respective rules.
This contract allows users to:
- Stake assets in specific campaigns, creating unique NFT positions.
- Partially or fully unstake assets, respecting lock periods.
- Claim accrued rewards without affecting their staked position.
Staking requires eligibility criteria to be met, and subsequent operations require ownership of the corresponding NFT as well._
CampaignDoesNotExist
Thrown when a staking campaign with the given invalidCampaignId
does not exist.
StakingPositionNotOwned
Thrown when nonOwnerAccount
does not own the staking position identified by nftId
.
InvalidUnlockTimestampAtRestake
Thrown at restake attemps with requested unlock timestamps that are before the existing one.
RewardsNotYetAvailableForPosition
Thrown when rewards are not yet available for the specified staking position.
StakingPositionCreated
Emitted at stake()
and stakeBeneficiary()
.
StakingPositionIncreased
Emitted at restake()
and restakeBeneficiary()
.
StakingPositionDecreased
Emitted at partialUnstake()
.
StakingPositionClosed
Emitted at fullyUnstake()
.
RewardsReceived
Emitted on condition at restake()
, restakeBeneficiary()
,
partialUnstake()
, fullyUnstake()
and getReward()
.
PositionBalanceUpdate
Emitted at stake()
, stakeBeneficiary()
, restake()
, restakeBeneficiary()
,
partialUnstake()
& fullyUnstake()
.
stake
Allows users to create a position within a specified campaign by allocating or locking assets that are predefined by the campaign's input configuration. The position is represented and tracked by an ERC721 NFT token, which is minted to the user upon staking.
_Instant stake rewards may or may not be featured, depending on the campaign's rewards distribution configuration.
A packet encapsulates individual or groups of different tokens with distinct ratios among them. The input packet for a campaign is defined by the creator of the campaign. Some examples of input packets are:
- packet = [2 Token A (ERC20)]
- packet = [5 Token A (ERC20), 10 Token B (ERC20)]
- packet = [3 Token A (ERC20), 2 Token C with ID == 9 (ERC1155)]
Users must meet eligibility criteria to create a position (see StakersEligibility
and AccessControl
facets).
Emits a {StakingPositionCreated}
and {PositionBalanceUpdate}
event._
Parameters
Name | Type | Description |
---|---|---|
campaignId | uint256 | The unique identifier of the targeted staking campaign in which the user is participating. |
amountOfPackets | uint256 | The number of input packets to stake. |
timeLockPeriod | uint256 | The duration, in seconds, during which the position's staked assets will be locked. |
stakeBeneficiary
Allows users to create a staking position within a specified campaign on behalf of a beneficiary, by locking assets that are predefined by the campaign's input configuration. The position is represented and tracked by an ERC721 NFT token, which is minted to the specified beneficiary upon staking.
_This function enables staking on behalf of another address (beneficiary
).
The staking input packets are transferred from the caller (msg.sender
), but the NFT staking position
and any instant stake rewards are allocated to the beneficiary. Instant stake rewards depend on the campaign's
reward distribution configuration.
IMPORTANT: Only the beneficiary must meet the eligibility criteria required to create a position
(see StakersEligibility
and AccessControl
facets).
Emits a {StakingPositionCreated}
and {PositionBalanceUpdate}
event.
For more information, see stake()
._
Parameters
Name | Type | Description |
---|---|---|
campaignId | uint256 | The unique identifier of the targeted staking campaign in which the user is participating. |
amountOfPackets | uint256 | The number of input packets to stake. |
timeLockPeriod | uint256 | The duration, in seconds, during which the position's staked assets will be locked. |
beneficiary | address | The address that will receive the NFT staking position and any instant rewards. |
_stakeBeneficiary
Internal version of stakeBeneficiary()
, handling staking logic for a specified beneficiary.
For more information, see stakeBeneficiary()
.
restake
Allows users to increase their position specified by nftId
by allocating or locking
additional amounts of staked assets defined in the associated campaign's input packet.
_Restake is not supported when instant staking rewards are featured.
Each position is associated with a specific campaign at the time it is created (see stake()
).
The recalculated unlockTimestamp
(block.timestamp + timeLockPeriod
)
must be greater than or equal to the current position's unlockTimestamp
.
Users must own the NFT representing the position they wish to increase and must meet eligibility criteria
(see StakersEligibility
and AccessControl
facets).
Emits a {StakingPositionIncreased}
and {PositionBalanceUpdate}
event.
Also emits a {RewardsReceived}
event on condition._
Parameters
Name | Type | Description |
---|---|---|
nftId | uint256 | The unique identifier of the NFT associated with the position. |
amountOfPackets | uint256 | The number of input packets to allocate on the existing position, thereby increasing it. |
timeLockPeriod | uint256 | The duration, in seconds, during which the position's staked assets will be locked. |
restakeBeneficiary
Allows users to increase a beneficiary's position specified by nftId
within a campaign
by allocating additional staked assets defined in the campaign's input packet.
_This function enables increasing an existing position on behalf of a beneficiary.
The staking input packets are transferred from the caller (msg.sender
), but any rewards are
allocated to the beneficiary. The beneficiary must own the NFT representing the position.
Restake is not supported when instant staking rewards are featured.
The recalculated unlockTimestamp
(block.timestamp + timeLockPeriod
) must be greater than or equal to
the current position's unlockTimestamp
.
IMPORTANT: Only the beneficiary must meet the eligibility criteria required to increase a position
(see StakersEligibility
and AccessControl
facets).
Emits a {StakingPositionIncreased}
and {PositionBalanceUpdate}
event.
Also emits a {RewardsReceived}
event on condition._
Parameters
Name | Type | Description |
---|---|---|
nftId | uint256 | The unique identifier of the NFT associated with the position. |
amountOfPackets | uint256 | The number of input packets to allocate to the existing position, increasing it. |
timeLockPeriod | uint256 | The duration, in seconds, for which the position's staked assets will be locked. |
beneficiary | address | The address that will receive any instant rewards and must own the NFT position. |
_restakeBeneficiary
Internal version of restakeBeneficiary()
, handling restaking logic for a specified beneficiary.
For more information, see restakeBeneficiary()
.
_applyRestakeAndTransferRewards
Called by _restakeBeneficiary()
.
Applies restake logic (specific to the employed RewardDistribution facet) and transfers the
calculated rewards (if any) to beneficiary
.
Emits a {RewardsReceived}
event on condition.
Parameters
Name | Type | Description |
---|---|---|
campaignId | uint256 | The unique identifier of the targeted staking campaign. |
nftId | uint256 | The unique identifier of the NFT associated with the position. |
getRestakeRewards | uint256 | The reward packets from IRewardsDistributionFacet.getRestakeReward() . |
rewardAssetHandler | address | The address of the campaign's rewards handler (see CampaignAssetManager.sol ) |
beneficiary | address | The address to receive the rewards |
partialUnstake
Allows users to decrease their position specified by nftId
by withdrawing
amounts of staked assets defined in the associated campaign's input packet.
_Partial unstaking is only supported when the position's lock period has expired.
Each position is associated with a specific campaign at the time it is created (see stake()
).
Claimable accrued rewards (if any) associated with the position are calculated and transferred to the owner of the position upon partial unstaking.
The amountOfPacketsToUnstake
must be less than the total staked input packets of the position.
Users must own the NFT representing the position they wish to decrease and must meet eligibility criteria
(see StakersEligibility
and AccessControl
facets).
Emits a {StakingPositionDecreased}
and {PositionBalanceUpdate}
event.
Also emits a {RewardsReceived}
event on condition._
Parameters
Name | Type | Description |
---|---|---|
nftId | uint256 | The unique identifier of the NFT associated with the position. |
amountOfPacketsToUnstake | uint256 | The number of input packets to withdraw from the position, thereby decreasing it. |
fullyUnstake
Allows users to close their position specified by nftId
by withdrawing
all the staked assets currently allocated to the position.
_Fully unstaking is only supported when the position's lock period has expired.
Users must own the NFT representing the position they wish to fully unstake and
must meet eligibility criteria (see StakersEligibility
and AccessControl
facets).
Claimable accrued rewards (if any) associated with the position are calculated and transferred to the owner of the position upon fully unstaking.
The NFT token representing the position is burned when the fully unstaking process is successful.
Emits a {StakingPositionClosed}
and {PositionBalanceUpdate}
event.
Also emits a {RewardsReceived}
event on condition._
Parameters
Name | Type | Description |
---|---|---|
nftId | uint256 | The unique identifier of the NFT associated with the position. |
getReward
Allows users to receive any accrued rewards associated with their position specified by nftId
.
This does not affect the total staked assets of the position.
_Users must own the NFT representing the position they wish to claim rewards from
and must meet eligibility criteria (see StakersEligibility
and AccessControl
facets).
Emits a {RewardsReceived}
event on condition._
Parameters
Name | Type | Description |
---|---|---|
nftId | uint256 | The unique identifier of the NFT associated with the position. |