Defi

了解 Synthetix Staking 合約中的 rewardRaterewardPerToken

  • March 17, 2022

Synthetix 質押合約甚至智能合約程序員的以下簡單質押合約中,有一些參數可以控制分散的獎勵,即rewardRaterewardPerToken

完整程式碼:

// 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

https://www.youtube.com/watch?v=LWWsjw3cgDk

https://www.youtube.com/watch?v=YqpRwJDz3xg

引用自:https://ethereum.stackexchange.com/questions/124024