meme币的彩票模型和流动性自动添加模型

这篇文章从合约代买的角度带大家了解一下 去年土狗风靡一时的彩票模型自动流动性添加模型

1、彩票模型:

核心每次交易的部分手续费进入彩票池,当彩票池中金额达到开奖标准,则随机在持有者中抽取一个钱包地址,转入奖金,当然,持有者必须符合持有一定代币数量,否则将本期奖金打入开发者钱包。

找了个之前买的meme币 catgirl
0x79eBC9A2ce02277A4b5b3A768b1C0A4ed75Bd936 来解读一下彩票的代码:

1.1 定义变量

mapping (address => uint256) private _rOwned;	// address=> 持币数量 映射

address[] private _addressList; // 存所有地址

address payable private _devWallet; // 开发者钱包
address private _lottoPotAddress; //抽奖地址
address private _lottoWalletAddress; // 抽奖钱包地址
uint256 public _lastLottoWinnerAmount; // 最后赢家奖金金额
uint256 public _totalLottoPrize;       // 总奖金金额 
uint public _lottoDrawCount = 0;       // 计数

uint256 public lotteryThreshold = 10 * 10**12 * 10**9;	 // 开奖阈值

bool inSwapAndLiquify;	// 是否已经进入流动性添加环节标志  默认为false
bool inLotteryDraw;	  // 是否已经进入开奖环节标志    默认为false

bool public swapAndLiquifyEnabled = true;	// 是否开启 自动加入流动性方法 标志
bool public lottoEnabled = true;          // 是否开启 彩票抽奖方法 标志
bool public _shouldSwapToBNB = false;

1.2 方法调用

合约 _transfer()方法中出现

function _transfer(	
    address from,	
    address to,	
    uint256 amount	
) private {	
	.......
	
	 // 查看 彩票奖池里的代币余额
	 uint256 lottoBalance = balanceOf(_lottoPotAddress);
	 // 彩票奖池中余额是否大于开奖阈值
	 bool overMinLottoBalance = lottoBalance >= lotteryThreshold;
	 if (
	     overMinLottoBalance && !inSwapAndLiquify && !inLotteryDraw && lottoEnabled
	 ) {
	     drawLotto(lottoBalance);
	 }
	......
}

开奖程序是否启动设置函数

function setLottoEnabled(bool enabled) public onlyOwner() {
    lottoEnabled = enabled;
}

彩票抽奖方法主方法:

event DrawLotto(uint256 amount, uint _lottoDrawCount);


// 函数修改器  修改进入流程标志
modifier lockTheLottery {	
    inLotteryDraw = true;	
    _;	
    inLotteryDraw = false;	
}

function lotterize() private view returns(address) {
	uint256 randomNumber = random().mod(_addressList.length);
	
	uint256 ownedAmount = _rOwned[_addressList[randomNumber]];
	// 如果随机的address 持有代币数量不足 直接打入开发者钱包
	if (ownedAmount >= _minLottoBalance) {
		return _addressList[randomNumber];
	}
	return _devWallet;
}

function drawLotto(uint256 amount) private lockTheLottery {
    _lottoWalletAddress = lotterize();
    // 此时将amount 转入 中奖者 地址 
    // 并且由于函数修改器 将inLotteryDraw = true 故再次转账时跳过抽奖环节
    _transfer(_lottoPotAddress, _lottoWalletAddress, amount);
    _lastLottoWinnerAmount = amount;
    // 总发出奖金
    _totalLottoPrize = _totalLottoPrize.add(amount);
    // 总开奖次数
    ++_lottoDrawCount;
    // 链上上报事件
    emit DrawLotto(amount, _lottoDrawCount);
}
    

2、流动性自动添加模型

流动性自动添加模型就是在每笔交易中收取一部分手续费,将其累计,当到达一定的金额,自动拿出积累的一半token换入 eth 组成[eth, token]交易对,注入流动池。这样会保证池子一直充盈,不会被大户交易吸干。

如果看懂了上面的彩票模型,那么流动性自动添加也是一个套路

event SwapAndLiquify(	
        uint256 tokensSwapped,	
        uint256 ethReceived,	
        uint256 tokensIntoLiqudity	
    );
function setSwapAndLiquifyEnabled(bool _enabled) public onlyOwner {	
    swapAndLiquifyEnabled = _enabled;	
    emit SwapAndLiquifyEnabledUpdated(_enabled);	
}	

每次调用_transfer()方法,进行一次流动性添加判断

function _transfer(	
    address from,	
    address to,	
    uint256 amount	
) private {	
		....
    // 查看 合约地址内的代币余额  每笔交易的手续费中一部分存在address(this) 中作为流动性储备
    uint256 contractTokenBalance = balanceOf(address(this));	
    // 查看 是否触发最大转账金额 默认_maxTxAmount 为代币对外总数量  10000 * 10**12 *10*9
    if(contractTokenBalance >= _maxTxAmount)	
    {	
        contractTokenBalance = _maxTxAmount;	
    }	
    // 持有数量是否 超过转移数量就加入流动性阈值
    // numTokensSellToAddToLiquidity 初始为 50 * 10**12 *10**9
    bool overMinTokenBalance = contractTokenBalance >= numTokensSellToAddToLiquidity;	
    if (	
        overMinTokenBalance && !inSwapAndLiquify &&	from != uniswapV2Pair && swapAndLiquifyEnabled	
    ) {	
        contractTokenBalance = numTokensSellToAddToLiquidity;	
        //add liquidity
        // 流动性添加	
        swapAndLiquify(contractTokenBalance);	
    }
	....
	}

进入swapAndLiquify() 方法

// 函数修改器 修改 流动性添加是否在进行的标志
modifier lockTheSwap {	
    inSwapAndLiquify = true;	
    _;	
    inSwapAndLiquify = false;	
}
function swapAndLiquify(uint256 contractTokenBalance) private lockTheSwap {	
    // split the contract balance into halves	
    // contractTokenBalance 的一半换成 eth
    uint256 half = contractTokenBalance.div(2);	
    uint256 otherHalf = contractTokenBalance.sub(half);	
    // capture the contract's current ETH balance.	
    // this is so that we can capture exactly the amount of ETH that the	
    // swap creates, and not make the liquidity event include any ETH that	
    // has been manually sent to the contract	
    // 查看初始时 address(this)中的eth数量
    uint256 initialBalance = address(this).balance;	
    // swap tokens for ETH
    // 换eth操作	
    swapTokensForEth(half); // <- this breaks the ETH -> HATE swap when swap+liquify is triggered	
    // how much ETH did we just swap into?
    // 换到了多少eth	
    uint256 newBalance = address(this).balance.sub(initialBalance);	
    // add liquidity to uniswap	
    // 一半contractTokenBalance  和 一半contractTokenBalance换的eth 添加进流动性池
    addLiquidity(otherHalf, newBalance);	
    // 报链上事件
    emit SwapAndLiquify(half, newBalance, otherHalf);	
}	
function swapTokensForEth(uint256 tokenAmount) private {	
    // generate the uniswap pair path of token -> weth	
    address[] memory path = new address[](2);	
    path[0] = address(this);	
    path[1] = uniswapV2Router.WETH();	
    _approve(address(this), address(uniswapV2Router), tokenAmount);	
    // make the swap	
    uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(	
        tokenAmount,	
        0, // accept any amount of ETH	
        path,	
        address(this),	
        block.timestamp	
    );	
}	
function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {	
    // approve token transfer to cover all possible scenarios	
    _approve(address(this), address(uniswapV2Router), tokenAmount);	
    // add the liquidity	
    uniswapV2Router.addLiquidityETH{value: ethAmount}(	
        address(this),	
        tokenAmount,	
        0, // slippage is unavoidable	
        0, // slippage is unavoidable	
        owner(),	
        block.timestamp	
    );	
}	
Subscribe to berwinYes
Receive the latest updates directly to your inbox.
Verification
This entry has been permanently stored onchain and signed by its creator.