30 amountIn不为零,为什么报错 PancakeLibrary: INSUFFICIENT_INPUT_AMOUNT

这个合约要在卖出的时候从滑点中扣除一部分兑换成USDT然后分给一些人,现在就在从滑点扣除后兑换成USDT这里出了问题。我在合约里将扣除的部分先转到合约里,然后查合约余额调用swapExactTokensForTokensSupportingFeeOnTransferTokens方法,报错PancakeLibrary: INSUFFICIENT_INPUT_AMOUNT,可是逻辑上应该是有值的,求大佬给看看问题出在哪里

contract TokenDistributor {
    constructor (address token) {
        //将代币全部授权给合约部署者,在这里是代币合约,让代币合约分配兑换到的代币资产
        IERC20(token).approve(msg.sender, uint(~uint256(0)));
    }
}

contract SAA is ERC20, Ownable {
    // 常量和状态变量优化:使用更紧凑的类型
    uint256 public lockPeriod; // 锁仓期
    uint256 private totalFee; // 滑点
    uint256 private baseFee; // 扣除滑点
    uint256 private referralFee; // 5%
    uint256 private buyFee; // 卖出手续费
    uint256[] private referralFees; // 推荐人手续费比例
    uint256[] private referralFeesNum; // 推荐人手续费达标人数

    TokenDistributor private _tokenDistributor; // 代币分发合约
    IInvite public inviteContract; // 推荐合约
    address public inviteContractAddress; // 推荐地址
    IPancakeRouter public pancakeRouter;
    IERC20 public immutable USDT;
    address public immutable pancakePair;
    address public feeReceiver;
    address public feeBuyer;
    address public tokenOwner;
    address public gainAddress;

    bool private inSwap;
    modifier lockTheSwap {
        require(!inSwap, "Already swapping");
        inSwap = true;
        _;
        inSwap = false;
    }

    // 合并相似的映射
    struct AccountInfo {
        uint256 acquireTime;
        bool isExcluded;
        bool isBlacklisted;
        bool isHolder;
        uint256 holderIndex;
    }
    mapping(address => AccountInfo) public accounts;
    address[] private holders;

    uint256 public maxTransactionAmount;
    uint256 public maxHoldingAmount;

    // 合并相似的事件
    event ConfigUpdated(string indexed param, uint256 value);
    event AddressUpdated(string indexed param, address addr);
    event TokenOperation(address indexed from, address indexed to, uint256 amount, string operation);

    constructor() ERC20('SAA', 'saa') {
        address _tokenOwner = 0x2bFB0C6c3c501092FE70420Cd6784F1832422c1B; // test
        address _pancakeRouter = 0xD99D1c33F9fC3444f8101754aBC46c52416550D1; // test
        address _usdt = 0x337610d27c682E347C9cD60BD4b3b107C9d34dDd; // test
        inviteContractAddress = 0x33b7415bebAEe63E1fe1E70ee85056AbC63aEc5b; // test
        address _feeReceiver = 0xEc9C8E1866761847E6d2e8398BA0dE5EBe4Da80d;
        address _feeBuyer = 0xEc9C8E1866761847E6d2e8398BA0dE5EBe4Da80d;
        address _gainAddress = 0x1d057F5489938Ba8477EC3d55DCe9ac0bc5482B0;

        inviteContract = IInvite(inviteContractAddress);
        pancakeRouter = IPancakeRouter(_pancakeRouter);
        USDT = IERC20(_usdt);
        feeReceiver = _feeReceiver;
        feeBuyer = _feeBuyer;
        tokenOwner = _tokenOwner;
        gainAddress = _gainAddress;
        _tokenDistributor = new TokenDistributor(_usdt);

        // 创建交易对
        pancakePair = IPancakeFactory(pancakeRouter.factory()).createPair(address(this), address(USDT));

        // 设置特权地址
        accounts[owner()].isExcluded = true;
        accounts[_tokenOwner].isExcluded = true;
        accounts[_feeReceiver].isExcluded = true;
        accounts[_feeBuyer].isExcluded = true;
        accounts[pancakePair].isExcluded = true;
        accounts[_pancakeRouter].isExcluded = true;
        accounts[address(this)].isExcluded = true;

        // 初始化代币和参数
        lockPeriod = 60 * 5;

        totalFee = 110;
        baseFee = 60;
        referralFee = 50;
        buyFee = 50;
        uint256 _totalSupply = 10000 * 10000 * 10 ** decimals();
        referralFees = [10, 10, 5, 5, 5, 5, 5, 5];
        referralFeesNum = [3, 6, 9, 12, 15, 18, 18, 18];
        maxTransactionAmount = _totalSupply * 5 / 100;
        maxHoldingAmount = _totalSupply * 10 / 100;

        _approve(address(this), address(pancakeRouter), type(uint256).max);
        USDT.approve(_pancakeRouter, type(uint256).max);

        _mint(_tokenOwner, _totalSupply);
    }

    function getTokenDistributor() external view returns (address) {
        return address(_tokenDistributor);
    }

    // 合并配置函数
    function updateConfig(string calldata param, uint256 value) external onlyOwner {
        if (keccak256(bytes(param)) == keccak256(bytes("lockPeriod"))) {
            require(value > 0, "Invalid lock period");
            lockPeriod = value;
        } else if (keccak256(bytes(param)) == keccak256(bytes("maxTransaction"))) {
            require(value > 0 && value <= maxHoldingAmount, "Invalid max transaction");
            maxTransactionAmount = value;
        } else if (keccak256(bytes(param)) == keccak256(bytes("maxHolding"))) {
            require(value >= maxTransactionAmount, "Invalid max holding");
            maxHoldingAmount = value;
        } else {
            revert("Invalid parameter");
        }
        emit ConfigUpdated(param, value);
    }

    // 合并地址更新函数
    function updateAddress(string calldata param, address addr) external onlyOwner {
        require(addr != address(0), "Invalid address");

        if (keccak256(bytes(param)) == keccak256(bytes("feeReceiver"))) {
            feeReceiver = addr;
        } else if (keccak256(bytes(param)) == keccak256(bytes("feeBuyer"))) {
            feeBuyer = addr;
        } else if (keccak256(bytes(param)) == keccak256(bytes("gainAddress"))) {
            gainAddress = addr;
        } else if (keccak256(bytes(param)) == keccak256(bytes("blacklist"))) {
            require(addr != owner() && addr != tokenOwner, "Protected address");
            accounts[addr].isBlacklisted = !accounts[addr].isBlacklisted;
        } else if (keccak256(bytes(param)) == keccak256(bytes("excludeFee"))) {
            accounts[addr].isExcluded = !accounts[addr].isExcluded;
        } else {
            revert("Invalid parameter");
        }
        emit AddressUpdated(param, addr);
    }

    function _updateHolders(address account) private {
        uint256 balance = balanceOf(account);
        AccountInfo storage info = accounts[account];

        if (balance > 0 && !info.isHolder) {
            holders.push(account);
            info.holderIndex = holders.length - 1;
            info.isHolder = true;
            emit TokenOperation(address(0), account, 0, "holder_added");
        } else if (balance == 0 && info.isHolder) {
            uint256 index = info.holderIndex;
            uint256 lastIndex = holders.length - 1;

            if (index != lastIndex) {
                address lastHolder = holders[lastIndex];
                holders[index] = lastHolder;
                accounts[lastHolder].holderIndex = uint16(index);
            }

            holders.pop();
            info.isHolder = false;
            emit TokenOperation(account, address(0), 0, "holder_removed");
        }
    }

    // 更换inviteContract
    function setInviteContract(address newInviteContract) external onlyOwner {
        require(newInviteContract != address(0), "Invalid invite contract");
        require(newInviteContract != inviteContractAddress, "Invalid invite contract");
        inviteContractAddress = newInviteContract;
        inviteContract = IInvite(inviteContractAddress);
    }

    // 修改referralFees
    function setReferralFees(uint256 _totalFee, uint256[] memory _referralFees, uint256[] memory _referralFeesNum) external onlyOwner {
        require(_totalFee >= 0 && _totalFee <= 1000, "Invalid total fee");
        uint256 _REFERRAL_FEE = 0;
        for (uint256 i = 0; i < _referralFees.length; i++) {
            require(_referralFees[i] >= 0 && _referralFees[i] <= 100, "Invalid referral fee");
            _REFERRAL_FEE += _referralFees[i];
        }
        require(_REFERRAL_FEE >= 1000, "Invalid referral fee");
        totalFee = _totalFee;
        referralFee = _REFERRAL_FEE;
        baseFee = _totalFee - _REFERRAL_FEE;
        referralFees = _referralFees;
        referralFeesNum = _referralFeesNum;
    }
    // 查看TOTAL_FEE, REFERRAL_FEE, BASE_FEE, referralFees
    function getReferralFees() external view returns (uint256, uint256, uint256, uint256[] memory, uint256[] memory) {
        return (totalFee, referralFee, baseFee, referralFees, referralFeesNum);
    }

    // 获取用户信息
    function getAccountInfo(address account) external view returns (bool isHolder, uint256 balance, uint256 acquireTime, bool isBlacklisted, bool isExcluded) {
        AccountInfo storage info = accounts[account];
        return (info.isHolder, balanceOf(account), info.acquireTime, info.isBlacklisted, info.isExcluded);
    }

    // 设置指定用户的排除属性
    function setExcluded(address account, bool isExcluded) external onlyOwner {
        require(account != address(0), "Invalid account");
        accounts[account].isExcluded = isExcluded;
    }

    // 设置指定用户的黑名单属性
    function setBlacklisted(address account, bool isBlacklisted) external onlyOwner {
        require(account != address(0), "Invalid account");
        accounts[account].isBlacklisted = isBlacklisted;
    }

    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override {
        require(from != address(0) && to != address(0) && amount > 0, "Invalid transfer");
        require(!accounts[from].isBlacklisted && !accounts[to].isBlacklisted, "Blacklisted");

        if (inSwap) {
            super._transfer(from, to, amount);
            return;
        }

        bool isSelling = to == pancakePair;
        bool isBuying = from == pancakePair;
        AccountInfo storage fromInfo = accounts[from];
        AccountInfo storage toInfo = accounts[to];
        AccountInfo storage originInfo = accounts[tx.origin];
        if(isBuying) {
            require(toInfo.isExcluded || originInfo.isExcluded, "cant buy");
            uint256 feeNum = (amount * buyFee) / 1000;
            amount -= feeNum;
            super._transfer(from, feeBuyer, feeNum);
            super._transfer(from, to, amount);
            return;
        }

        if (isSelling) {
            if (fromInfo.isExcluded) {
                super._transfer(from, to, amount);
            } else {
            //     require(block.timestamp >= fromInfo.acquireTime + lockPeriod, "Locked");

                uint256 totalNum = (amount * totalFee) / 1000;
                uint256 baseNum = (amount * baseFee) / 1000;
                uint256 referralNum = totalNum - baseNum;

                super._transfer(from, feeReceiver, baseNum);
                super._transfer(from, address(this), referralNum);
                amount -= totalNum;
                super._transfer(from, to, amount);
                _distributeFees();

                _updateHolders(from);
            }
            return;
        }

        if (!isBuying && !isSelling) {
            require(fromInfo.isExcluded, "Transfer not allowed: sender not excluded");
            super._transfer(from, to, amount);
            if (accounts[to].acquireTime == 0) {
                accounts[to].acquireTime = block.timestamp;
            }
            _updateHolders(to);
        }
    }

    function _distributeFees() private lockTheSwap {
        uint256 totalNum = balanceOf(address(this));
        require(totalNum > 0, "No fees to distribute");
        // 设置兑换路径
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = address(USDT);

        // 执行兑换,使用更长的截止时间
        pancakeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            totalNum,
            0, // 接受任何数量的USDT
            path,
            address(_tokenDistributor),
            block.timestamp + 300 // 5分钟的缓冲时间
        );

        // 兑换成功,继续处理
        uint256 receivedUsdt = USDT.balanceOf(address(_tokenDistributor));

        // 计算referralFees总和
        uint256 totalReferralFees = 0;
        for (uint256 i = 0; i < referralFees.length; i++) {
            totalReferralFees += referralFees[i];
        }

        // 按比例分配USDT
        address current = tx.origin;
        uint256 remainingUsdt = receivedUsdt;

        for (uint256 i = 0; i < referralFees.length && remainingUsdt > 0; i++) {
            current = inviteContract.getReferrer(current);
            if (current == address(0)) break;

            uint256 referralCount = inviteContract.getReferralCount(current);
            if (referralCount >= referralFeesNum[i]) {
                // 按照referralFees[i]在totalReferralFees中的比例计算USDT数量
                uint256 usdtShare = (receivedUsdt * referralFees[i]) / totalReferralFees;
                if (usdtShare > remainingUsdt) usdtShare = remainingUsdt;

                if (usdtShare > 0) {
                    require(USDT.transferFrom(address(_tokenDistributor), current, usdtShare), "USDT transfer failed");
                    remainingUsdt -= usdtShare;
                }
            }
        }

        // 将剩余的USDT发送给gainAddress
        if (remainingUsdt > 0) {
            require(USDT.transferFrom(address(_tokenDistributor), gainAddress, remainingUsdt), "USDT transfer failed");
        }
    }

    // 必要的公共查询函数
    function getTokenHolders() external view returns (address[] memory) {
        address[] memory result = new address[](holders.length);
        uint256 count = 0;

        for (uint256 i = 0; i < holders.length; i++) {
            address holder = holders[i];
            if (holder != tokenOwner && holder != pancakePair && holder != feeReceiver && balanceOf(holder) > 0) {
                result[count++] = holder;
            }
        }

        assembly {
            mstore(result, count)
        }
        return result;
    }

    // 减少指定账户代币10%
    function reduceAccountBalance(address account, uint256 percent) external onlyOwner {
        require(account != address(0), "Invalid address");
        require(percent > 0 && percent <= 1000, "Invalid percent");

        uint256 currentBalance = balanceOf(account);
        require(currentBalance > 0, "Account has no balance");

        // 计算要减少的金额
        uint256 amountToReduce = (currentBalance * percent) / 1000;
        require(amountToReduce > 0, "Amount to reduce is too small");

        // 从账户中销毁代币
        _burn(account, amountToReduce);

        // 更新持有者列表
        _updateHolders(account);
    }

    // 减少币对中代币数量使价格提高percent/1000
    function increasePriceByTenPercent(uint256 percent) external onlyOwner {
        require(percent > 0 && percent <= 1000, "Invalid percent");
        // 获取币对中的储备量
        (uint112 reserve0, uint112 reserve1, ) = IPancakePair(pancakePair).getReserves();

        // 确定我们的代币是token0还是token1
        address token0 = IPancakePair(pancakePair).token0();
        uint112 ourReserve = address(this) == token0 ? reserve0 : reserve1;

        // 为了提高价格percent/1000
        uint256 amountToReduce = uint256(ourReserve) - uint256(ourReserve) * 1000 / (1000 + percent);
        require(amountToReduce > 0, "Amount to reduce is too small");

        // 从币对中移除代币并销毁
        // 注意:这里我们直接从币对地址销毁代币,这会减少流动性池中的代币数量
        _burn(pancakePair, amountToReduce);
    }
}
请先 登录 后评论
  • 0 关注
  • 0 收藏,143 浏览
  • maliang 提出于 1天前