python编程示例系列
python编程示例系列二
python的Web神器Streamlit
怎样应聘高薪职位
C#视觉应用开辟问题系列
c#串口应用开辟问题系列
microPython Python最小内核源码解析
NI-motion运动控制c语言示例代码解析
# 流动性挖矿技能详解
用途
流动性挖矿(Liquidity Mining)是去中心化金融(DeFi)中的一种紧张机制,主要用途包括:
- 吸引流动性提供者:通过代币鼓励吸引用户向协议提供流动性
- 促进代币分发:以公平方式将代币分发给现实参与协议的用户
- 建立深度市场:资助新兴项目快速建立交易深度,低落滑点
- 促进协议发展:增长协议的总锁仓代价(TVL),提高协议的可信度和利用率
原理
流动性挖矿的基本原理是:
- 用户向流动性池提供资产对(如ETH/USDT)
- 作为回报,用户得到LP(流动性提供者)代币,证明其在池中的份额
- 协议向LP代币持有者分发奖励代币,通常按时间和提供的流动性比例盘算
- 用户可以随时取回其提供的流动性,同时停止得到奖励
实现代码示例
以下是一个基于Solidity的流动性挖矿合约示例:
- // SPDX-License-Identifier: MIT
- pragma solidity ^0.8.0;
- import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
- import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
- import "@openzeppelin/contracts/access/Ownable.sol";
- import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
- /**
- * @title 流动性挖矿合约
- * @dev 一个简单的流动性挖矿实现,用户可以质押LP代币来赚取奖励代币
- */
- contract LiquidityMining is Ownable, ReentrancyGuard {
- using SafeERC20 for IERC20;
-
- // 质押的LP代币
- IERC20 public lpToken;
-
- // 奖励代币
- IERC20 public rewardToken;
-
- // 每秒释放的奖励代币数量
- uint256 public rewardRate;
-
- // 上次更新奖励的时间戳
- uint256 public lastUpdateTime;
-
- // 每单位质押代币累积的奖励
- uint256 public rewardPerTokenStored;
-
- // 总质押量
- uint256 public totalStaked;
-
- // 结束时间
- uint256 public periodFinish;
-
- // 挖矿时长
- uint256 public duration;
-
- // 用户信息映射
- mapping(address => uint256) public userRewardPerTokenPaid;
- mapping(address => uint256) public rewards;
- mapping(address => uint256) public balances;
-
- // 事件
- event Staked(address indexed user, uint256 amount);
- event Withdrawn(address indexed user, uint256 amount);
- event RewardPaid(address indexed user, uint256 reward);
- event RewardsDurationUpdated(uint256 newDuration);
-
- /**
- * @dev 构造函数
- * @param _lpToken 质押的LP代币地址
- * @param _rewardToken 奖励代币地址
- * @param _duration 挖矿持续时间(秒)
- */
- constructor(address _lpToken, address _rewardToken, uint256 _duration) {
- lpToken = IERC20(_lpToken);
- rewardToken = IERC20(_rewardToken);
- duration = _duration;
- }
-
- /**
- * @dev 返回当前时间戳或结束时间(取较小值)
- */
- function lastTimeRewardApplicable() public view returns (uint256) {
- return block.timestamp < periodFinish ? block.timestamp : periodFinish;
- }
-
- /**
- * @dev 计算每个质押代币应得的奖励数量
- */
- function rewardPerToken() public view returns (uint256) {
- if (totalStaked == 0) {
- return rewardPerTokenStored;
- }
-
- return rewardPerTokenStored + (
- (lastTimeRewardApplicable() - lastUpdateTime) * rewardRate * 1e18 / totalStaked
- );
- }
-
- /**
- * @dev 计算用户当前可领取的奖励
- * @param account 用户地址
- */
- function earned(address account) public view returns (uint256) {
- return (
- balances[account] * (rewardPerToken() - userRewardPerTokenPaid[account]) / 1e18
- ) + rewards[account];
- }
-
- /**
- * @dev 更新奖励相关变量
- * @param account 用户地址(可选)
- */
- modifier updateReward(address account) {
- rewardPerTokenStored = rewardPerToken();
- lastUpdateTime = lastTimeRewardApplicable();
-
- if (account != address(0)) {
- rewards[account] = earned(account);
- userRewardPerTokenPaid[account] = rewardPerTokenStored;
- }
- _;
- }
-
- /**
- * @dev 质押LP代币
- * @param amount 质押数量
- */
- function stake(uint256 amount) external nonReentrant updateReward(msg.sender) {
- require(amount > 0, "Cannot stake 0");
-
- totalStaked += amount;
- balances[msg.sender] += amount;
-
- // 转移LP代币到合约
- lpToken.safeTransferFrom(msg.sender, address(this), amount);
-
- emit Staked(msg.sender, amount);
- }
-
- /**
- * @dev 提取质押的LP代币
- * @param amount 提取数量
- */
- function withdraw(uint256 amount) public nonReentrant updateReward(msg.sender) {
- require(amount > 0, "Cannot withdraw 0");
- require(balances[msg.sender] >= amount, "Not enough staked");
-
- totalStaked -= amount;
- balances[msg.sender] -= amount;
-
- // 返还LP代币给用户
- lpToken.safeTransfer(msg.sender, amount);
-
- emit Withdrawn(msg.sender, amount);
- }
-
- /**
- * @dev 领取奖励
- */
- function getReward() public nonReentrant updateReward(msg.sender) {
- uint256 reward = rewards[msg.sender];
- if (reward > 0) {
- rewards[msg.sender] = 0;
- rewardToken.safeTransfer(msg.sender, reward);
- emit RewardPaid(msg.sender, reward);
- }
- }
-
- /**
- * @dev 退出:提取所有质押并领取奖励
- */
- function exit() external {
- withdraw(balances[msg.sender]);
- getReward();
- }
-
- /**
- * @dev 添加奖励代币到合约
- * @param reward 奖励代币数量
- */
- function notifyRewardAmount(uint256 reward) external onlyOwner updateReward(address(0)) {
- // 处理重复调用的情况
- if (block.timestamp >= periodFinish) {
- rewardRate = reward / duration;
- } else {
- uint256 remaining = periodFinish - block.timestamp;
- uint256 leftover = remaining * rewardRate;
- rewardRate = (reward + leftover) / duration;
- }
-
- // 确保合约有足够的奖励代币
- uint256 balance = rewardToken.balanceOf(address(this));
- require(rewardRate <= balance / duration, "Reward too high");
-
- lastUpdateTime = block.timestamp;
- periodFinish = block.timestamp + duration;
- }
-
- /**
- * @dev 更新挖矿时长
- * @param _duration 新的时长(秒)
- */
- function setRewardsDuration(uint256 _duration) external onlyOwner {
- require(block.timestamp > periodFinish, "Previous rewards period not complete");
- duration = _duration;
- emit RewardsDurationUpdated(_duration);
- }
- }
复制代码 逻辑流程图
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
|