Overview
The liquidity mining staker design is comprised of one canonical position staking contract, Staker. The technical reference for this contract is here and the source code is here.
Data Structures
State:
Params:
Incentives
createIncentive(CreateIncentiveParams memory params)
createIncentive(CreateIncentiveParams memory params)
createIncentive
creates a liquidity mining incentive program. The key used to look up an Incentive is the hash of its immutable properties.
Check:
Incentive with these params does not already exist
Timestamps:
params.endTime >= params.startTime
,params.startTime >= block.timestamp
Incentive with this ID does not already exist.
Effects:
Sets
incentives[key] = Incentive(totalRewardUnclaimed=totalReward, totalSecondsClaimedX128=0, rewardToken=rewardToken)
Interaction:
Transfers
params.totalReward
frommsg.sender
to self.Make sure there is a check here and it fails if the transfer fails
Emits
IncentiveCreated
endIncentive(EndIncentiveParams memory params)
endIncentive(EndIncentiveParams memory params)
endIncentive
can be called by anyone to end an Incentive after the endTime
has passed, transferring totalRewardUnclaimed
of rewardToken
back to refundee
.
Check:
block.timestamp > params.endTime
Incentive exists (
incentive.totalRewardUnclaimed != 0
)
Effects:
deletes
incentives[key]
(This is a new change)
Interactions:
safeTransfers
totalRewardUnclaimed
ofrewardToken
to the incentive creatormsg.sender
emits
IncentiveEnded
Deposit/Withdraw Token
Interactions
nonfungiblePositionManager.safeTransferFrom(sender, this, tokenId)
This transfer triggers the onERC721Received hook
onERC721Received(address, address from, uint256 tokenId, bytes calldata data)
onERC721Received(address, address from, uint256 tokenId, bytes calldata data)
Check:
Make sure sender is dragonswapV2 nft
Effects:
Creates a deposit for the token setting deposit
owner
tofrom
.Setting
owner
tofrom
ensures that the owner of the token also owns the deposit. Approved addresses and operators may first transfer the token to themselves before depositing for deposit ownership.
If
data.length>0
, stakes the token in one or more incentives
withdrawToken(uint256 tokenId, address to, bytes memory data)
withdrawToken(uint256 tokenId, address to, bytes memory data)
Checks
Check that a Deposit exists for the token and that
msg.sender
is theowner
on that Deposit.Check that
numberOfStakes
on that Deposit is 0.
Effects
Delete the Deposit
delete deposits[tokenId]
.
Interactions
safeTransferFrom
the token toto
withdata
.emit
DepositTransferred(token, deposit.owner, address(0))
Stake/Unstake/Rewards
stakeToken
stakeToken
Check:
deposits[params.tokenId].owner == msg.sender
Make sure incentive actually exists and has reward that could be claimed (incentive.rewardToken != address(0))
Check if this check can check totalRewardUnclaimed instead
Make sure token not already staked
claimReward
claimReward
Interactions
msg.sender
to withdraw all of their reward balance in a specific token to a specifiedto
address.emit RewardClaimed(to, reward)
unstakeToken
unstakeToken
To unstake an NFT, you call unstakeToken
, which takes all the same arguments as stake
.
Checks
It checks that you are the owner of the Deposit
It checks that there exists a
Stake
for the provided key (with exists=true).
Effects
Deletes the Stake.
Decrements
numberOfStakes
for the Deposit by 1.totalRewardsUnclaimed
is decremented byreward
.totalSecondsClaimed
is incremented byseconds
.Increments
rewards[rewardToken][msg.sender]
by the amount given bygetRewardInfo
.
getRewardInfo
getRewardInfo
It computes
secondsInsideX128
(the total liquidity seconds for which rewards are owed) for a given Stake, by:using
snapshotCumulativesInside
from the DragonswapV2 core contract to getsecondsPerLiquidityInRangeX128
, and subtractingsecondsPerLiquidityInRangeInitialX128
.Multiplying that by
stake.liquidity
to get the total seconds accrued by the liquidity in that period
Note that X128 means it's a
UQ32X128
.It computes
totalSecondsUnclaimed
by takingmax(endTime, block.timestamp) - startTime
, casting it as a Q128, and subtractingtotalSecondsClaimedX128
.It computes
rewardRate
for the Incentive castingincentive.totalRewardUnclaimed
as a Q128, then dividing it bytotalSecondsUnclaimedX128
.reward
is then calculated assecondsInsideX128
times therewardRate
, scaled down to a regular uint128.
Last updated