代币的核心转账代码如下:
function _transfer(
address from,
address to,
uint256 amount
) private {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
console.log(from,to,amount);
console.log('inSwapAndLiquify',inSwapAndLiquify);
console.log(balanceOf(from),balanceOf(to));
require(amount > 0 && amount <= balanceOf(from), "Sender insufficient funds");
bool shouldSetInviter = balanceOf(to) == 0 &&
inviter[to] == address(0) &&
from != uniswapV2Pair &&
!isContract(from) && !isContract(to);
bool needLiquidity = false;
bool takeFee = true;
uint256 destroyAmount = balanceOf(_destroyAddress);
if (_isExcludedFromFee[from] || _isExcludedFromFee[to] || destroyAmount >= _tTotalMaxFee) {
takeFee = false;
}else{
//必须是转入或者转出交易所的时候才会触发分红和扣税
if(from != uniswapV2Pair && to != uniswapV2Pair && from != address(uniswapV2Router)){
takeFee = false;
}else{
if (to == address(uniswapV2Router)){
takeFee = false;
}else{
//合约自身持币数量要大于拿来回流的数量
uint256 contractTokenBalance = balanceOf(address(this));
bool overMinTokenBalance = contractTokenBalance >= amount.mul(liquidityDivisor.add(fundDivisor)).div(1000);
if (overMinTokenBalance &&
!inSwapAndLiquify &&
swapAndLiquifyEnabled
) { //卖出或者添加流动性,买入或者撤除流动性的时候
//当目的转账地址是lp流动池地址时将触发swapAndLiquify动作,将转账金的2%的一半换eth再与另一半加入流动池
needLiquidity = true;
// if (needLiquidity){
uint256 swapAmount = amount.div(1000).mul(liquidityDivisor);
//swap and add liquidity添加流动性
swapAndLiquify(swapAmount);
//补回因为做流动性而损失在此合约上的代币数量
_takeLiquidity(swapAmount);
//处理兑换其他代币的部分
if (fundDivisor>0 && fundAddress!=address(0)){
uint256 swapAmount1 = amount.div(1000).mul(fundDivisor);
swapAndExchange(swapAmount1);
//补回兑换其他代币损失的代币
_takeLiquidity(swapAmount1);
}
// }
}
}
}
}
console.log(takeFee, needLiquidity);
_tokenTransfer(from, to, amount, takeFee, needLiquidity);
console.log(balanceOf(from),balanceOf(to));
//锁定推荐关系
if (shouldSetInviter) {
inviter[to] = from;
}
console.log(takeFee, needLiquidity);
}
function _tokenTransfer(
address sender,
address recipient,
uint256 tAmount,
bool takeFee,
bool needLiquidity
) private {
uint256 currentRate = _getRate();
uint256 rAmount = tAmount.mul(currentRate);
console.log(_rOwned[sender],rAmount,currentRate);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
uint256 rate = 0;
if (takeFee) {
if (feeLevels>0){
_takeInviterFee(sender, recipient, tAmount, currentRate);//分发推荐奖励
}
if (destroyRate>0){
_takeTransfer(
sender,_destroyAddress,tAmount.div(1000).mul(destroyRate),currentRate);
}
//如果开通了回流流动池以及兑换其他代币就需要把他们的税率加上
if (needLiquidity){
rate = destroyRate + liquidityDivisor;
//如果兑换其他代币的fundAddress地址和兑换税率有设置,就得把此部分税率加上
if (fundDivisor>0 && fundAddress != address(0)){
rate = rate + fundDivisor;
}
}else{
rate = destroyRate;
}
for (uint i=0; i<feeLevels; i++){
rate += feeRate[i];
}
}
uint256 recipientRate = 1000 - rate;
if (rate>0){
_rOwned[recipient] = _rOwned[recipient].add(
rAmount.div(1000).mul(recipientRate));
emit Transfer(sender, recipient, tAmount.div(1000).mul(recipientRate));
}else{
_rOwned[recipient] = _rOwned[recipient].add(rAmount);
emit Transfer(sender, recipient, tAmount);
}
console.log(rAmount.div(1000).mul(recipientRate),rate);
}
function _takeInviterFee(
address sender,
address recipient,
uint256 tAmount,
uint256 currentRate
) private {
address cur;
address reciver;
uint256 curTAmount;
uint256 curRAmount;
if (sender == uniswapV2Pair ||sender == address(uniswapV2Router)) {
cur = recipient;
} else {
cur = sender;
}
for (uint256 i = 0; i < feeLevels; i++) {
// uint256 rate = 1;
// uint256 minBalance;
curTAmount = tAmount.div(1000).mul(feeRate[i]);
curRAmount = curTAmount.mul(currentRate);
cur = inviter[cur];
// if (cur == address(0) || balanceOf(cur) < minBalance) {
if (cur == address(0)) {
reciver = _destroyAddress;
}else{
reciver = cur;
}
if (curTAmount>0){
if (!_isExcludedFromFee[reciver]) {
//加入判断此人是否是分红黑名单,是的话不能分红
_rOwned[reciver] = _rOwned[reciver].add(curRAmount);
emit Transfer(sender, reciver, curTAmount);
}else{
_rOwned[_destroyAddress] = _rOwned[_destroyAddress].add(curRAmount);
emit Transfer(sender, _destroyAddress, curTAmount);
}
}
}
}