一、说明
直接在合约中调用uniswap v2的router地址创建本币和ETH或者Usdt的交易对地址。交易对地址即添加流动性的lp合约地址。在部署合约时需要预先生成LP的合约地址,才能实现针对不同的交易对自动添加流动性(回流筑底池)和LP分红ETH/USDT。这样的需求在BSC,ARB等ERC20公链上是非常普通的需求。但是,同样的代码如果部署到ETH以太坊主网上,在部署合约时会因gas费用评估异常,导致合约部署失败。失败的主要原因如下:
- 在构造函数中调用了usdt.approve接口,授权usdt在合约地址上无限大额度到uniswapv2Router。ETH上直接调用usdt的approve方法是无法评估gas费用的。因此该功能代码端需要单独拆分出来以降低gas费用
- 构造函数中直接调用uniswapv2Router的swapFactory.createPair方法创建资金池地址即LP合约地址,造成评估gas费用异常
- 构造函数中调用了_allowances[address(this)][address(swapRouter)] = MAX;代码段导致gas费用评估过高
- 构造函数中调用了其他ERC20标准的接口函数导致gas费用评估异常
二、解决方案
- 将构造函数中针对usdt的approve操作单独拆分出来
- 将构造函数中直接创建本币和eth或者usdt的交易对拆分成单独的函数,手动调用接口触发
- 通过设置资金池lp地址变量方式,变现替代从合约中创建资金池地址方式
- 自动回流筑底池和LP分红ETH/USDT尽量通过定量分发的方式,每次触发LP分红ETH都设置固定的笔数,避免交易手续费gas费用过高,导致的交易失败
- 自动回流筑底池优先选择ETH的池子,因为usdt的池子需要做两步跨池交易,增加了一倍的gas费用消耗
三、核心代码实现:
- 构造函数如下所示,只做基本的变量初始化,把其他可能导致gas费用过高的功能代码全部拆分出去:
/**
* @dev Sets the values for {name} and {symbol}.
*
* The defaut value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor (
address fundAddress,
address marketingAddress,
address usdtAddress,
uint256 minNum,
uint256 killStartBlockNumber,
uint256 killBotBatchBlockNumber
) {
_fundAddress = fundAddress;
_marketingAddress = marketingAddress;
_usdtAddress = usdtAddress;
killBlockNumber = killStartBlockNumber;
killBatchBlockNumber = killBotBatchBlockNumber;
numTokensSellToAddToLiquidity = minNum * 10 ** uint256(_decimals);
_isExcludedFromFee[owner()] = true;
_isExcludedFromFee[fundAddress] = true;
_isExcludedFromFee[marketingAddress] = true;
_isExcludedFromFee[address(this)] = true;
_balances[_msgSender()] = _totalSupply;
emit Transfer(address(0), _msgSender(), _totalSupply);
}
2. 手动创建本币和ETH的交易对功能:
function launchWethSwap() external onlyOwner() {
require(!launchWethSwapEnabled,"launchWethSwapEnabled is already open");
_uniswapV2Router = uniswapV2Router;
_allowances[address(this)][address(uniswapV2Router)] = MAX_UINT256;
_uniswapV2Pair = IUniswapV2Factory(uniswapV2Router.factory()).createPair(address(this), uniswapV2Router.WETH());
uniswapV2Router.addLiquidityETH{value: address(this).balance}(address(this),balanceOf(address(this)),0,0,owner(),block.timestamp);
_swapPairList[_uniswapV2Pair] = true;
IERC20(_uniswapV2Pair).approve(address(uniswapV2Router), type(uint256).max);
_isExcludedFromFee[address(uniswapV2Router)] = true;
launchWethSwapEnabled = true;
}
3. 手动创建针对本币和usdt的交易对函数接口:
function launchUsdtSwap() external onlyOwner() {
require(!launchUsdtSwapEnabled,"launchUsdtSwapEnabled is already open");
if(_uniswapV2Pair == address(0)) {
_uniswapV2Router = uniswapV2Router;
_isExcludedFromFee[address(uniswapV2Router)] = true;
_allowances[address(this)][address(uniswapV2Router)] = MAX_UINT256;
}
IERC20(_usdtAddress).approve(address(_uniswapV2Router), MAX_UINT256);
_uniswapV2UsdtPair = IUniswapV2Factory(_uniswapV2Router.factory()).createPair(address(this), _usdtAddress);
_swapPairList[_uniswapV2UsdtPair] = true;
IERC20(_uniswapV2UsdtPair).approve(address(uniswapV2Router), type(uint256).max);
launchUsdtSwapEnabled = true;
}
4. 直接设置本币和ETH或者usdt交易对资金池的函数接口,提到通过合约创建资金池地址,避免因手续费gas过高导致资金池对创建失败
function setUniswapV2Pair(address _swapPair) public onlyOwner {
_uniswapV2Router = uniswapV2Router;
_allowances[address(this)][address(uniswapV2Router)] = MAX_UINT256;
_uniswapV2Pair = _swapPair;
_swapPairList[_uniswapV2Pair] = true;
_isExcludedFromFee[address(uniswapV2Router)] = true;
}
function setUniswapV2UsdtPair(address _swapUsdtPair) public onlyOwner {
if(_uniswapV2Pair == address(0)) {
_uniswapV2Router = uniswapV2Router;
_isExcludedFromFee[address(uniswapV2Router)] = true;
_allowances[address(this)][address(uniswapV2Router)] = MAX_UINT256;
}
IERC20(_usdtAddress).approve(address(_uniswapV2Router), MAX_UINT256);
_uniswapV2UsdtPair = _swapUsdtPair;
_swapPairList[_uniswapV2UsdtPair] = true;
}
5. 自动回流筑底池合约代码段:
if (lpAmount > 0) {
uint256 lpFist = fistBalance.mul(lpFee).div(swapFee).div(2);
if (lpFist > 0 && liquifyEnabled) {
_swapRouter.addLiquidity(
address(this), _fist, otherlpAmount, lpFist, 0, 0, fundAddress, block.timestamp
);
emit SwapAndLiquify(halflpAmount, lpFist, otherlpAmount);
}
}
6. 按照用户持有的LP权重分红ETH/usdt代码段:
function processReward(uint256 gas) private {
if (progressRewardBlock.add(progressRewardBlockDebt) > block.number) {
return;
}
IERC20 FIST = IERC20(_fist);
if (balance < holderRewardCondition) {
return;
}
IERC20 holdToken = IERC20(_mainPair);
address shareHolder;
uint256 tokenBalance;
uint256 amount;
uint256 shareholderCount = holders.length;
uint256 gasUsed = 0;
uint256 iterations = 0;
uint256 gasLeft = gasleft();
uint256 holdCondition = holderCondition;
while (gasUsed < gas && iterations < shareholderCount) {
shareHolder = holders[currentIndex];
tokenBalance = holdToken.balanceOf(shareHolder);
if (tokenBalance >= holdCondition && !excludeHolder[shareHolder]) {
amount = balance.div(holdTokenTotal);
if (amount > 0) {
_takeInviterReward(shareHolder, amount);
}
}
gasUsed = gasUsed + (gasLeft - gasleft());
gasLeft = gasleft();
currentIndex++;
iterations++;
}
progressRewardBlock = block.number;
}
四、完整版合约源代码如下:
源码及合约部署、开源、上线交易所、动态参数配置教程下载地址:
至此,完成直接在合约中创建基于uniswap V2的交易对实现自动筑底池和LP分红ETH/Usdt功能所有操作流程。
pdf+视频币安智能链BSC发币教程及多模式组合合约源代码下载:
币安智能链BSC发币(合约部署、开源、锁仓、LP、参数配置、开发、故障处理、工具使用)教程下载:
多模式(燃烧、回流指定营销地址、分红本币及任意币种,邀请推广八代收益,LP加池分红、交易分红、复利分红、NFT分红、自动筑池、动态手续费、定时开盘、回购)组合合约源代码下载:
pdf+视频币安智能链BSC发币教程及多模式组合合约源代码下载地址:
添加VX或者telegram获取全程线上免费指导
评论前必须登录!
注册