Defi了解 Synthetix Staking 合約中的
了解 Synthetix Staking 合約中的 rewardRate
和 rewardPerToken
在Synthetix 質押合約甚至智能合約程序員的以下簡單質押合約中,有一些參數可以控制分散的獎勵,即
rewardRate
和rewardPerToken
。完整程式碼:
// SPDX-License-Identifier: MIT pragma solidity ^0.8; contract StakingRewards { IERC20 public rewardsToken; IERC20 public stakingToken; uint public rewardRate = 100; uint public lastUpdateTime; uint public rewardPerTokenStored; mapping(address => uint) public userRewardPerTokenPaid; mapping(address => uint) public rewards; uint private _totalSupply; mapping(address => uint) private _balances; constructor(address _stakingToken, address _rewardsToken) { stakingToken = IERC20(_stakingToken); rewardsToken = IERC20(_rewardsToken); } function rewardPerToken() public view returns (uint) { if (_totalSupply == 0) { return rewardPerTokenStored; } return rewardPerTokenStored + (((block.timestamp - lastUpdateTime) * rewardRate * 1e18) / _totalSupply); } function earned(address account) public view returns (uint) { return ((_balances[account] * (rewardPerToken() - userRewardPerTokenPaid[account])) / 1e18) + rewards[account]; } modifier updateReward(address account) { rewardPerTokenStored = rewardPerToken(); lastUpdateTime = block.timestamp; rewards[account] = earned(account); userRewardPerTokenPaid[account] = rewardPerTokenStored; _; } function stake(uint _amount) external updateReward(msg.sender) { _totalSupply += _amount; _balances[msg.sender] += _amount; stakingToken.transferFrom(msg.sender, address(this), _amount); } function withdraw(uint _amount) external updateReward(msg.sender) { _totalSupply -= _amount; _balances[msg.sender] -= _amount; stakingToken.transfer(msg.sender, _amount); } function getReward() external updateReward(msg.sender) { uint reward = rewards[msg.sender]; rewards[msg.sender] = 0; rewardsToken.transfer(msg.sender, reward); } } interface IERC20 { function totalSupply() external view returns (uint); function balanceOf(address account) external view returns (uint); function transfer(address recipient, uint amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint amount) external returns (bool); function transferFrom( address sender, address recipient, uint amount ) external returns (bool); event Transfer(address indexed from, address indexed to, uint value); event Approval(address indexed owner, address indexed spender, uint value); }
我很難理解所有的功能。
那些有意義的:
earned
: function 清楚地說明了使用者賺了多少錢。我很難相處的人:
rewardRate
:這就像每個令牌每秒的獎勵嗎?rewardPerToken
:這顯然是每個抵押代幣的獎勵,但為什麼總供應量在函式中被劃分?任何和所有的幫助表示讚賞。
rewardRate
是每秒的獎勵,這個速率將乘以token user staked / total staked
rewardPerToken
- 數學技巧
R
=獎勵率
l(t)
= 使用者當時質押的數量t
L(t)
= 總質押金額t
獲得的獎勵總額為
R*l(t) / L(t)
l(t)
除非使用者下注或取消下注,否則是恆定的所以上面的等式可以重寫為它也可以寫成
rewardPerTokenStored
是左總和乘以回報率
userRewardPerToken[user]
是正確的總和乘以回報率參考
https://www.paradigm.xyz/2021/05/liquidity-mining-on-uniswap-v3
https://www.youtube.com/watch?v=6ZO5aYg1GI8