qidao123.com技术社区-IT企服评测·应用市场

 找回密码
 立即注册

虚拟币用到的非常哇塞的技能(流动性挖矿)解读

[复制链接]
发表于 2025-5-24 14:06:35 | 显示全部楼层 |阅读模式
python编程示例系列
python编程示例系列二
python的Web神器Streamlit
怎样应聘高薪职位
C#视觉应用开辟问题系列
c#串口应用开辟问题系列
microPython Python最小内核源码解析
NI-motion运动控制c语言示例代码解析
# 流动性挖矿技能详解
用途

流动性挖矿(Liquidity Mining)是去中心化金融(DeFi)中的一种紧张机制,主要用途包括:

  • 吸引流动性提供者:通过代币鼓励吸引用户向协议提供流动性
  • 促进代币分发:以公平方式将代币分发给现实参与协议的用户
  • 建立深度市场:资助新兴项目快速建立交易深度,低落滑点
  • 促进协议发展:增长协议的总锁仓代价(TVL),提高协议的可信度和利用率
原理

流动性挖矿的基本原理是:

  • 用户向流动性池提供资产对(如ETH/USDT)
  • 作为回报,用户得到LP(流动性提供者)代币,证明其在池中的份额
  • 协议向LP代币持有者分发奖励代币,通常按时间和提供的流动性比例盘算
  • 用户可以随时取回其提供的流动性,同时停止得到奖励
实现代码示例

以下是一个基于Solidity的流动性挖矿合约示例:
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.0;
  3. import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
  4. import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
  5. import "@openzeppelin/contracts/access/Ownable.sol";
  6. import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
  7. /**
  8. * @title 流动性挖矿合约
  9. * @dev 一个简单的流动性挖矿实现,用户可以质押LP代币来赚取奖励代币
  10. */
  11. contract LiquidityMining is Ownable, ReentrancyGuard {
  12.     using SafeERC20 for IERC20;
  13.    
  14.     // 质押的LP代币
  15.     IERC20 public lpToken;
  16.    
  17.     // 奖励代币
  18.     IERC20 public rewardToken;
  19.    
  20.     // 每秒释放的奖励代币数量
  21.     uint256 public rewardRate;
  22.    
  23.     // 上次更新奖励的时间戳
  24.     uint256 public lastUpdateTime;
  25.    
  26.     // 每单位质押代币累积的奖励
  27.     uint256 public rewardPerTokenStored;
  28.    
  29.     // 总质押量
  30.     uint256 public totalStaked;
  31.    
  32.     // 结束时间
  33.     uint256 public periodFinish;
  34.    
  35.     // 挖矿时长
  36.     uint256 public duration;
  37.    
  38.     // 用户信息映射
  39.     mapping(address => uint256) public userRewardPerTokenPaid;
  40.     mapping(address => uint256) public rewards;
  41.     mapping(address => uint256) public balances;
  42.    
  43.     // 事件
  44.     event Staked(address indexed user, uint256 amount);
  45.     event Withdrawn(address indexed user, uint256 amount);
  46.     event RewardPaid(address indexed user, uint256 reward);
  47.     event RewardsDurationUpdated(uint256 newDuration);
  48.    
  49.     /**
  50.      * @dev 构造函数
  51.      * @param _lpToken 质押的LP代币地址
  52.      * @param _rewardToken 奖励代币地址
  53.      * @param _duration 挖矿持续时间(秒)
  54.      */
  55.     constructor(address _lpToken, address _rewardToken, uint256 _duration) {
  56.         lpToken = IERC20(_lpToken);
  57.         rewardToken = IERC20(_rewardToken);
  58.         duration = _duration;
  59.     }
  60.    
  61.     /**
  62.      * @dev 返回当前时间戳或结束时间(取较小值)
  63.      */
  64.     function lastTimeRewardApplicable() public view returns (uint256) {
  65.         return block.timestamp < periodFinish ? block.timestamp : periodFinish;
  66.     }
  67.    
  68.     /**
  69.      * @dev 计算每个质押代币应得的奖励数量
  70.      */
  71.     function rewardPerToken() public view returns (uint256) {
  72.         if (totalStaked == 0) {
  73.             return rewardPerTokenStored;
  74.         }
  75.         
  76.         return rewardPerTokenStored + (
  77.             (lastTimeRewardApplicable() - lastUpdateTime) * rewardRate * 1e18 / totalStaked
  78.         );
  79.     }
  80.    
  81.     /**
  82.      * @dev 计算用户当前可领取的奖励
  83.      * @param account 用户地址
  84.      */
  85.     function earned(address account) public view returns (uint256) {
  86.         return (
  87.             balances[account] * (rewardPerToken() - userRewardPerTokenPaid[account]) / 1e18
  88.         ) + rewards[account];
  89.     }
  90.    
  91.     /**
  92.      * @dev 更新奖励相关变量
  93.      * @param account 用户地址(可选)
  94.      */
  95.     modifier updateReward(address account) {
  96.         rewardPerTokenStored = rewardPerToken();
  97.         lastUpdateTime = lastTimeRewardApplicable();
  98.         
  99.         if (account != address(0)) {
  100.             rewards[account] = earned(account);
  101.             userRewardPerTokenPaid[account] = rewardPerTokenStored;
  102.         }
  103.         _;
  104.     }
  105.    
  106.     /**
  107.      * @dev 质押LP代币
  108.      * @param amount 质押数量
  109.      */
  110.     function stake(uint256 amount) external nonReentrant updateReward(msg.sender) {
  111.         require(amount > 0, "Cannot stake 0");
  112.         
  113.         totalStaked += amount;
  114.         balances[msg.sender] += amount;
  115.         
  116.         // 转移LP代币到合约
  117.         lpToken.safeTransferFrom(msg.sender, address(this), amount);
  118.         
  119.         emit Staked(msg.sender, amount);
  120.     }
  121.    
  122.     /**
  123.      * @dev 提取质押的LP代币
  124.      * @param amount 提取数量
  125.      */
  126.     function withdraw(uint256 amount) public nonReentrant updateReward(msg.sender) {
  127.         require(amount > 0, "Cannot withdraw 0");
  128.         require(balances[msg.sender] >= amount, "Not enough staked");
  129.         
  130.         totalStaked -= amount;
  131.         balances[msg.sender] -= amount;
  132.         
  133.         // 返还LP代币给用户
  134.         lpToken.safeTransfer(msg.sender, amount);
  135.         
  136.         emit Withdrawn(msg.sender, amount);
  137.     }
  138.    
  139.     /**
  140.      * @dev 领取奖励
  141.      */
  142.     function getReward() public nonReentrant updateReward(msg.sender) {
  143.         uint256 reward = rewards[msg.sender];
  144.         if (reward > 0) {
  145.             rewards[msg.sender] = 0;
  146.             rewardToken.safeTransfer(msg.sender, reward);
  147.             emit RewardPaid(msg.sender, reward);
  148.         }
  149.     }
  150.    
  151.     /**
  152.      * @dev 退出:提取所有质押并领取奖励
  153.      */
  154.     function exit() external {
  155.         withdraw(balances[msg.sender]);
  156.         getReward();
  157.     }
  158.    
  159.     /**
  160.      * @dev 添加奖励代币到合约
  161.      * @param reward 奖励代币数量
  162.      */
  163.     function notifyRewardAmount(uint256 reward) external onlyOwner updateReward(address(0)) {
  164.         // 处理重复调用的情况
  165.         if (block.timestamp >= periodFinish) {
  166.             rewardRate = reward / duration;
  167.         } else {
  168.             uint256 remaining = periodFinish - block.timestamp;
  169.             uint256 leftover = remaining * rewardRate;
  170.             rewardRate = (reward + leftover) / duration;
  171.         }
  172.         
  173.         // 确保合约有足够的奖励代币
  174.         uint256 balance = rewardToken.balanceOf(address(this));
  175.         require(rewardRate <= balance / duration, "Reward too high");
  176.         
  177.         lastUpdateTime = block.timestamp;
  178.         periodFinish = block.timestamp + duration;
  179.     }
  180.    
  181.     /**
  182.      * @dev 更新挖矿时长
  183.      * @param _duration 新的时长(秒)
  184.      */
  185.     function setRewardsDuration(uint256 _duration) external onlyOwner {
  186.         require(block.timestamp > periodFinish, "Previous rewards period not complete");
  187.         duration = _duration;
  188.         emit RewardsDurationUpdated(_duration);
  189.     }
  190. }
复制代码
逻辑流程图


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|qidao123.com技术社区-IT企服评测▪应用市场 ( 浙ICP备20004199|浙ICP备20004199号 )|网站地图

GMT+8, 2025-8-11 12:16 , Processed in 0.083195 second(s), 32 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表