这类项目的基本是:转账/交易会收取 2%的利息以及 3%的流动性费用(数据来自Pig),2%的利息直接均匀分发给持币人(也就是rbase或ampl那一套),3%则在达到一定金额后自动卖掉1.5%的Token,然后提供流动性,这样流动性池子将持续变大(该部分流动性权益存放在Token合约中),不能取出。
由于transfer逻辑异常复杂,有各种手续费收取判断(白名单)以及自动提供逻辑性逻辑(超过一定金额),因此gas费较高。猜测rbase死掉可能是由于eth gas过高,而bsc上gas低得多,所以活得很好?
// 单纯的常量,用于计算份额
uint256 private constant MAX = ~uint256(0);
// 代币总量
uint256 private _tTotal = 1000000000 * 10**6 * 10**9;
// 份额总量,其实就是一个极大的值,但是又不超限溢出的目的
uint256 private _rTotal = (MAX - (MAX % _tTotal));
// 真实表示用于的份额,然后乘以总量就是他的余额
mapping (address => uint256) private _rOwned;
// 被排除掉不需要手续费的用户余额,因此每一次切换用户手续费收取的时候,
// 这里都要重新更新 _rOwned 和 _tOwned 值
mapping (address => uint256) private _tOwned;
// balanceOf定义:
// 如果是不需要手续费用户,直接调用 _tOwned数据
// 否则调用 tokenFromReflection 取
function balanceOf(address account) public view override returns (uint256) {
if (_isExcluded[account]) return _tOwned[account];
return tokenFromReflection(_rOwned[account]);
}
// 含义就是 rOwned占用总份额再乘以总量,其实也就是余额了
// 这里 getRate比较复杂,是因为要计算总份额,里面有包含不需要手续费账户
// 具体可以去源码看,粗略看理解含义即可
function tokenFromReflection(uint256 rAmount) public view returns(uint256) {
require(rAmount <= _rTotal, "Amount must be less than total reflections");
uint256 currentRate = _getRate();
return rAmount.div(currentRate);
}
// 这里贴一个 To 不需要手续费的例子,方便理解
// 由于from是需要手续费,因此from直接减掉份额的
// 需要将它加上不需要手续费列表的时候,直接清掉份额同时计算汇率即可,具体见: includeInReward 函数
// 而to不需要手续费,因此直接加余额到 tOwned
// 但由于未来to可能要被挪掉手续费权限,因此他也备份计算了一个 rOwned(但读取余额时不用)
// 挪掉的时候直接去除权限,然后取 rOwned 值即可,具体见: excludeFromReward 函数
function _transferToExcluded(address sender, address recipient, uint256 tAmount) private {
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
_tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
_rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
_takeLiquidity(tLiquidity);
_reflectFee(rFee, tFee);
emit Transfer(sender, recipient, tTransferAmount);
}
// 获取本次转账实际份额
// t系列用于tOwned也就是排除手续费的用户金额计算
// r系列用于rOwned也就是正常需要扣除手续费的用户份额(金额)计算
// 相当于全部换算好汇率了,这样子transfer的时候就可以直接算了
function _getValues(uint256 tAmount) private view returns (uint256, uint256, uint256, uint256, uint256, uint256) {
(uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getTValues(tAmount);
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee) = _getRValues(tAmount, tFee, tLiquidity, _getRate());
return (rAmount, rTransferAmount, rFee, tTransferAmount, tFee, tLiquidity);
}
// 用于统计一下手续费总量
uint256 private _tFeeTotal;
// 用于控制是否不收取手续费,比如管理员是不收取的..
mapping (address => bool) private _isExcludedFromFee;
mapping (address => bool) private _isExcluded;
address[] private _excluded;
// 小数,其实就是为了让他看起来很大,这一系列都是9位小数
uint8 private _decimals = 9;
// 转账手续费,具体逻辑是转账的时候减少其到账金额
// 这部分手续费是通过减少总份额来控制,这样相当于平分给持币人
// 也可以理解成通缩,因为总量虽然看起来没变,但其实持币人金额变大,相当于总量减少
// 也可以理解为rebase,因为每个人余额都变多了,类似于ampl
uint256 public _taxFee = 2;
// uniswap/pancakeswap 地址,pair地址是自动生成的(调用uni接口即可)
IUniswapV2Router02 public immutable uniswapV2Router;
address public immutable uniswapV2Pair;
// 用于lock锁,同时只允许一笔提供流动性的操作
bool inSwapAndLiquify;
// 是否开启自动添加流动性权限
// 如果未开启,则代币锁在Token合约中,不会去提供流动性
bool public swapAndLiquifyEnabled = true;
// 表示非管理员下最大可转账金额(管理员不受限制),可以通过管理员修改
uint256 public _maxTxAmount = 5000000 * 10**6 * 10**9;
// 流动性抽水以及自动提供流动性的阈值,逻辑:
// 每一笔转账都有一个_liquidityFee(见前面)将被扣除放到 Token 合约中,比如pig目前是3%
// 3%金额将自动去uni_router卖掉一半成为bnb/eth,然后再添加流动性
// 流动性权限属于合约, 目前没有接口把这个流动性取出来,相当于锁死了
uint256 public _liquidityFee = 3;
uint256 private numTokensSellToAddToLiquidity = 500000 * 10**6 * 10**9;