我的本意是swap兑换时收取滑点,将滑点在兑换成USDT后转入指定地址, 但是现在一兑换就报错UniswapV2: TRANSFER_FAILED 请大佬解惑 交易对就是代币对USDT 0x81243a879538Afc45C6259130F00F307F16e2550是测试链USDT合约 `// SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
interface IPancakeRouter { function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts); }
interface IPancakePair { function sync() external; }
interface IUniswapFactory { function getPair(address tokenA, address tokenB) external view returns (address pair); function createPair(address tokenA, address tokenB) external returns (address pair); }
contract TokenDistributor { constructor(address token) { IERC20(token).approve(msg.sender, type(uint256).max); // 授权给 router } }
contract BBXToken is ERC20, Ownable, ReentrancyGuard { using Address for address;
uint256 public immutable TOTAL_SUPPLY;
uint256 public buyTax = 1000; // 10%
uint256 public sellTax = 3000; // 30%
address public buyTaxWallet = 0x918f2aF5376a8B83a099a97DAB18b8ee63CFbC7a;
address public sellTaxWallet = 0x918f2aF5376a8B83a099a97DAB18b8ee63CFbC7a;
address public usdtToken = 0x81243a879538Afc45C6259130F00F307F16e2550;
address public liquidityPool;
address public mintSenderAddress = 0x918f2aF5376a8B83a099a97DAB18b8ee63CFbC7a; // 只允许当前用户铸造代币
uint256 public burnRate = 300;
uint256 public lastBurnTime;
uint256 public lastBurnGapTime = 1 days;
uint256 public mintTotal;
IPancakeRouter public pancakeRouter;
TokenDistributor public _tokenDistributor;
bool private isInSwap;
mapping(address => bool) private isExcludedFromFee;
modifier onlyMint() {
require(msg.sender == mintSenderAddress, "must be mint sender");
_;
}
modifier lockTheSwap {
isInSwap = true;
_;
isInSwap = false;
}
constructor(address initialOwner, address _router, address _factory) ERC20("BBX", "BBX") Ownable(initialOwner) {
TOTAL_SUPPLY = 10_000_000 * 10 ** decimals();
_mint(initialOwner, 100000 ether);
mintTotal += 100000 ether;
isExcludedFromFee[initialOwner] = true;
isExcludedFromFee[address(this)] = true;
pancakeRouter = IPancakeRouter(_router);
lastBurnTime = block.timestamp;
_tokenDistributor = new TokenDistributor(usdtToken);
isExcludedFromFee[address(_tokenDistributor)] = true;
liquidityPool = IUniswapFactory(_factory).createPair(address(this), usdtToken);
_approve(address(this), liquidityPool, type(uint256).max);
_approve(address(this), _router, type(uint256).max);
IERC20(usdtToken).approve(_router, type(uint256).max);
IERC20(usdtToken).approve(address(this), type(uint256).max);
}
function totalSupply() public view override returns (uint256) {
return TOTAL_SUPPLY;
}
function mint(address _address, uint256 _amount) external onlyMint {
require(_amount > 0, "must be greater than 0");
require(mintTotal + _amount <= TOTAL_SUPPLY, "max mint");
super._mint(_address, _amount);
mintTotal += _amount;
}
function transfer(address recipient, uint256 amount) public override returns (bool) {
if (block.timestamp >= lastBurnTime + lastBurnGapTime) {
uint256 totalNum = this.balanceOf(liquidityPool);
uint256 burnNum = totalNum * burnRate / 10000;
super._transfer(liquidityPool, address(0xdead), burnNum);
IPancakePair(liquidityPool).sync();
}
address sender = msg.sender;
if (isExcludedFromFee[sender] || isExcludedFromFee[recipient]) {
super._transfer(sender, recipient, amount);
return true;
}
if (_isBuy(sender)) {
uint256 taxAmount = (amount * buyTax) / 10000;
uint256 amountAfterTax = amount - taxAmount;
uint256 tax1 = (taxAmount * 20) / 30; // 20% 直接转给 buyTaxWallet
uint256 tax2 = (taxAmount * 10) / 30; // 10% 换 targetToken
super._transfer(sender, buyTaxWallet, tax1);
super._transfer(sender, recipient, amountAfterTax);
if (!isInSwap) {
super._transfer(sender, address(this), tax2);
_swapToTargetToken(buyTaxWallet, tax2); // 兑换USDT,再兑换目标代币
}
} else if (_isSell(recipient)) {
uint256 taxAmount = (amount * sellTax) / 10000;
uint256 amountAfterTax = amount - taxAmount;
uint256 tax1 = (taxAmount * 20) / 30; // 20% 换 targetToken
uint256 tax2 = (taxAmount * 10) / 30; // 10% 直接转给 sellTaxWallet
super._transfer(sender, sellTaxWallet, tax2);
super._transfer(sender, recipient, amountAfterTax);
if (!isInSwap) {
super._transfer(sender, address(this), tax1);
_swapToTargetToken(buyTaxWallet, tax1); // 兑换USDT,再兑换目标代币
}
} else {
super._transfer(sender, recipient, amount);
}
return true;
}
function _isBuy(address sender) private view returns (bool) {
return sender == liquidityPool;
}
function _isSell(address recipient) private view returns (bool) {
return recipient == liquidityPool;
}
function _swapToTargetToken(address to, uint256 amount) private lockTheSwap {
require(balanceOf(address(this)) >= amount, "Not enough tokens");
address[] memory path1 = new address[](2);
path1[0] = address(this);
path1[1] = usdtToken;
pancakeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
amount,
0, // 设置合理的 amountOutMin
path1,
address(to),
block.timestamp + 300
);
uint256 usdtBalance = IERC20(usdtToken).balanceOf(address(_tokenDistributor));
require(usdtBalance > 0, "Swap to USDT failed");
}
function getAmountOutMin(uint256 amountIn, address[] memory path) private view returns (uint256) {
uint256[] memory amounts = pancakeRouter.getAmountsOut(amountIn, path);
return amounts[amounts.length - 1];
}
function setLiquidityPool(address pool) external onlyOwner {
liquidityPool = pool;
_approve(address(this), liquidityPool, type(uint256).max);
}
function setBuyTaxWallet(address _buyTaxWallet) external onlyOwner {
buyTaxWallet = _buyTaxWallet;
}
function setSellTaxWallet(address _sellTaxWallet) external onlyOwner {
sellTaxWallet = _sellTaxWallet;
}
function setTargetToken(address _targetToken) external onlyOwner {
targetToken = _targetToken;
}
function setUsdtToken(address _usdtToken) external onlyOwner {
usdtToken = _usdtToken;
}
function setMintSenderAddress(address _mintSenderAddress) external onlyOwner {
mintSenderAddress = _mintSenderAddress;
}
function setBurnRate(uint256 _burnRate) external onlyOwner {
burnRate = _burnRate;
}
function setLastBurnGapTime(uint256 _lastBurnGapTime) external onlyOwner {
lastBurnGapTime = _lastBurnGapTime;
}
function setMintTotal(uint256 _mintTotal) external onlyOwner {
mintTotal = _mintTotal;
}
function excludeFromFee(address account, bool excluded) external onlyOwner {
isExcludedFromFee[account] = excluded;
}
receive() external payable nonReentrant {
require(msg.value > 0, "No BNB sent");
payable(mintSenderAddress).transfer(msg.value); // 转给 mint sender
}
}`