ERC20代币在PancakeSwap买卖时如何设置划转交易税费
PancakeSwap ERC20代币买卖税费实现方案
你之前的交易方向判定逻辑是正确的:
- 当转账
to地址为PancakeSwap交易对地址时,属于用户卖出操作 - 当转账
from地址为PancakeSwap交易对地址时,属于用户买入操作
两类税费的具体实现方式如下,全部逻辑可直接在OpenZeppelin ERC20的_transfer钩子函数中落地。
前置配置
首先在合约中定义必要的状态变量,全程用整数运算避免浮点精度问题:
// PancakeSwap路由合约地址 IPancakeRouter02 public immutable pancakeRouter; // PancakeSwap本币-WBNB交易对地址 address public immutable pancakePair; // 税费接收地址(Owner) address public immutable taxReceiver; // 白名单映射,名单内地址转账不扣税 mapping(address => bool) public whiteList; // 3%税率,以10000为基数计算 uint256 public constant TAX_RATE = 300; uint256 public constant RATE_DENOMINATOR = 10000; // 防重入锁,避免兑换税费时触发循环扣税 bool private _inSwapProcess; modifier lockSwap() { _inSwapProcess = true; _; _inSwapProcess = false; }
部署合约时需要在构造函数中初始化路由、交易对地址,同时将Owner、路由地址、合约自身地址、后续的流动性锁仓地址加入白名单,避免添加流动性、合约自动兑换税费时被误扣税。
卖出场景:3%代币税费直接划转Owner
卖出是用户将代币转入交易对兑换BNB的过程,全程在ERC20转账逻辑内完成,不需要额外交互,直接拆分转账金额即可:
- 拦截
to == pancakePair且不在白名单、不在自动兑换流程中的转账 - 计算3%的税费金额,直接将这部分代币从用户地址转到Owner地址
- 剩余97%的代币正常转入交易对,完成卖出流程
买入场景:3% BNB税费划转Owner
买入是用户将BNB转入交易对兑换代币的过程,ERC20合约本身没有直接操作用户BNB的权限,通用落地逻辑是:
- 拦截
from == pancakePair且不在白名单、不在自动兑换流程中的转账 - 拆分交易对转出的代币:97%正常转给买入用户,3%的税费代币留在合约地址
- 合约调用PancakeSwap路由,将这3%的税费代币卖出兑换为BNB,兑换所得直接转到Owner地址
该逻辑是目前链上带BNB分红/税费代币的通用实现,因税费占比极低,产生的滑点可以忽略,不会破坏交易对恒定乘积定价。
完整_transfer逻辑参考
function _transfer( address from, address to, uint256 amount ) internal override { require(from != address(0), "zero address"); require(to != address(0), "zero address"); // 白名单地址转账无税 if (whiteList[from] || whiteList[to] || _inSwapProcess) { super._transfer(from, to, amount); return; } // 卖出逻辑:to为交易对,扣3%代币给Owner if (to == pancakePair) { uint256 taxAmount = amount * TAX_RATE / RATE_DENOMINATOR; uint256 actualAmount = amount - taxAmount; super._transfer(from, taxReceiver, taxAmount); super._transfer(from, to, actualAmount); return; } // 买入逻辑:from为交易对,扣3%代币换BNB给Owner if (from == pancakePair) { uint256 taxAmount = amount * TAX_RATE / RATE_DENOMINATOR; uint256 actualAmount = amount - taxAmount; super._transfer(from, address(this), taxAmount); super._transfer(from, to, actualAmount); // 兑换税费代币为BNB if (taxAmount > 0) _swapTaxForBNB(taxAmount); return; } // 普通链上转账无税 super._transfer(from, to, amount); } // 税费代币兑换BNB内部函数 function _swapTaxForBNB(uint256 tokenAmount) internal lockSwap { _approve(address(this), address(pancakeRouter), tokenAmount); address[] memory path = new address[](2); path[0] = address(this); path[1] = pancakeRouter.WETH(); pancakeRouter.swapExactTokensForETHSupportingFeeOnTransferTokens( tokenAmount, 0, path, taxReceiver, block.timestamp ); }
上线前必须检查的注意点
- 不要提前硬编码交易对地址,部署合约后先创建交易对,再将交易对地址写入合约配置,否则会出现买卖方向判定错误
- 必须给路由合约开放代币转账的免税权限,否则添加流动性、兑换税费时会重复扣税
- 因为存在3%的买卖税,用户在PancakeSwap交易时需要将滑点 tolerance 设置到3%以上,否则交易可能失败
- 可以根据需求设置最小兑换阈值,比如累计税费代币价值达到0.05BNB时才触发兑换,降低小额交易的gas消耗
- 兑换逻辑必须加防重入锁,避免被恶意构造交易触发重入漏洞
内容的提问来源于stack exchange,提问作者SumoKichi
相关产品推荐
相关产品推荐

