You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PancakeSwap控制单个钱包流动性供给上限至总供应量3%?

能否在PancakeSwap限制单个钱包的流动性供给量?

可行性结论

能实现,但没法直接用PancakeSwap官方合约完成——你得自定义合约来限制单个钱包的流动性存入上限。PancakeSwap的核心AMM合约(比如UniswapV2Pair)本身没内置单钱包额度限制逻辑,必须通过额外的合约层或者修改相关合约来达成需求。你的目标(单钱包上限为总供应量3200万的3%,即960万代币)完全可以实现。

实现方案与代码示例

方案:自定义流动性代理合约

写一个代理合约,要求用户必须通过这个合约向PancakeSwap添加流动性。合约在执行添加操作前,会检查该钱包已存入的流动性对应的目标代币量是否超过960万的上限。

以下是核心Solidity代码示例(适配BSC网络):

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@pancakeswap/pancake-swap-core/contracts/interfaces/IPancakePair.sol";
import "@pancakeswap/pancake-swap-core/contracts/interfaces/IPancakeFactory.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

// 加入重入防护,避免安全漏洞
contract LiquidityLimiter is ReentrancyGuard {
    IPancakeFactory public immutable factory;
    address public immutable targetToken;
    address public immutable quoteToken; // 比如WBNB
    address public pair;
    uint256 public constant MAX_PER_WALLET = 9_600_000 * 10**18; // 假设目标代币是18位小数,按需调整

    constructor(address _factory, address _targetToken, address _quoteToken) {
        factory = IPancakeFactory(_factory);
        targetToken = _targetToken;
        quoteToken = _quoteToken;
        pair = factory.getPair(_targetToken, _quoteToken);
        require(pair != address(0), "Liquidity pair doesn't exist");
    }

    // 计算用户已存入的流动性对应的目标代币数量
    function getUserDepositedTargetToken(address user) public view returns (uint256) {
        uint256 userLPBalance = IPancakePair(pair).balanceOf(user);
        uint256 totalLP = IPancakePair(pair).totalSupply();
        if (totalLP == 0) return 0;
        
        // 判断目标代币是reserve0还是reserve1
        bool isTargetToken0 = IPancakePair(pair).token0() == targetToken;
        uint256 targetReserve = isTargetToken0 ? IPancakePair(pair).reserve0() : IPancakePair(pair).reserve1();
        
        return (userLPBalance * targetReserve) / totalLP;
    }

    // 代理添加流动性,用户需先授权合约转移目标代币和报价代币
    function addLiquidity(
        uint256 targetAmountDesired,
        uint256 quoteAmountDesired,
        uint256 targetAmountMin,
        uint256 quoteAmountMin,
        address to
    ) external nonReentrant {
        uint256 currentDeposited = getUserDepositedTargetToken(msg.sender);
        
        // 计算本次添加的目标代币实际数量(按池内比例)
        (uint256 reserve0, uint256 reserve1, ) = IPancakePair(pair).getReserves();
        bool isTargetToken0 = IPancakePair(pair).token0() == targetToken;
        uint256 targetReserve = isTargetToken0 ? reserve0 : reserve1;
        uint256 quoteReserve = isTargetToken0 ? reserve1 : reserve0;

        uint256 targetAmount = targetAmountDesired;
        uint256 quoteAmount = (targetAmountDesired * quoteReserve) / targetReserve;
        
        if (quoteAmount > quoteAmountDesired) {
            targetAmount = (quoteAmountDesired * targetReserve) / quoteReserve;
            quoteAmount = quoteAmountDesired;
        }

        // 检查是否超过上限
        require(currentDeposited + targetAmount <= MAX_PER_WALLET, "Exceeds max liquidity per wallet");

        // 转移代币到合约
        IERC20(targetToken).transferFrom(msg.sender, address(this), targetAmount);
        IERC20(quoteToken).transferFrom(msg.sender, address(this), quoteAmount);

        // 授权给流动性池合约
        IERC20(targetToken).approve(pair, targetAmount);
        IERC20(quoteToken).approve(pair, quoteAmount);

        // 调用PancakeSwap mint流动性
        (uint256 targetOut, uint256 quoteOut, uint256 liquidity) = IPancakePair(pair).mint(to);

        // 退回多余的代币给用户
        if (targetOut < targetAmount) {
            IERC20(targetToken).transfer(msg.sender, targetAmount - targetOut);
        }
        if (quoteOut < quoteAmount) {
            IERC20(quoteToken).transfer(msg.sender, quoteAmount - quoteOut);
        }
    }
}

关键说明

  1. 依赖与部署:部署时需要传入PancakeSwap工厂合约地址(BSC主网:0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73)、你的目标代币地址和报价代币地址(比如WBNB)。
  2. 小数位数适配:代码中MAX_PER_WALLET假设代币是18位小数,如果你的代币小数位数不同,要调整10**18为对应值。
  3. 安全防护:加入了ReentrancyGuard防止重入攻击,部署前务必在测试网(如BSC Testnet)做全面测试。

替代方案

如果你是自定义代币的发行方,也可以在代币合约中添加逻辑:当用户将代币转入PancakeSwap流动性池时,检查该用户已存入池中的代币总量是否超过上限。但这种方式只能限制单方向的代币存入,灵活性不如代理合约。

内容的提问来源于stack exchange,提问作者user3033562

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 15:45:01