欢迎订阅专栏:3分钟Solidity--智能合约--Web3区块链技术必学
离散质押奖励
如需获取此内容的最新版本,请参阅 Cyfrin.io 上的离散质押奖励(代码示例)
在DeFi领域,离散质押奖励是一种常见的激励机制,它与连续质押奖励在计算和发放方式上有所不同。简单来说,离散质押奖励并非随时间连续累积,而是在特定的时间点或事件触发时发放。
与质押奖励合约类似。不同之处在于奖励金额每秒都可能变化。
Discrete Staking Rewards
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
contract DiscreteStakingRewards {
IERC20 public immutable stakingToken;
IERC20 public immutable rewardToken;
mapping(address => uint256) public balanceOf;
uint256 public totalSupply;
uint256 private constant MULTIPLIER = 1e18;
uint256 private rewardIndex;
mapping(address => uint256) private rewardIndexOf;
mapping(address => uint256) private earned;
constructor(address _stakingToken, address _rewardToken) {
stakingToken = IERC20(_stakingToken);
rewardToken = IERC20(_rewardToken);
}
function updateRewardIndex(uint256 reward) external {
rewardToken.transferFrom(msg.sender, address(this), reward);
rewardIndex += (reward * MULTIPLIER) / totalSupply;
}
function _calculateRewards(address account)
private
view
returns (uint256)
{
uint256 shares = balanceOf[account];
return (shares * (rewardIndex - rewardIndexOf[account])) / MULTIPLIER;
}
function calculateRewardsEarned(address account)
external
view
returns (uint256)
{
return earned[account] + _calculateRewards(account);
}
function _updateRewards(address account) private {
earned[account] += _calculateRewards(account);
rewardIndexOf[account] = rewardIndex;
}
function stake(uint256 amount) external {
_updateRewards(msg.sender);
balanceOf[msg.sender] += amount;
totalSupply += amount;
stakingToken.transferFrom(msg.sender, address(this), amount);
}
function unstake(uint256 amount) external {
_updateRewards(msg.sender);
balanceOf[msg.sender] -= amount;
totalSupply -= amount;
stakingToken.transfer(msg.sender, amount);
}
function claim() external returns (uint256) {
_updateRewards(msg.sender);
uint256 reward = earned[msg.sender];
if (reward > 0) {
earned[msg.sender] = 0;
rewardToken.transfer(msg.sender, reward);
}
return reward;
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount)
external
returns (bool);
function allowance(address owner, address spender)
external
view
returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount)
external
returns (bool);
}