Pig

简介

PigToken是一个代码完全抄袭 safemoon 的版本,而safemoon来源于当时的 rbase项目(https://etherscan.io/address/0xe8b251822d003a2b2466ee0e38391c2db2048739#codearrow-up-right),有理由相信,他们可能是同一个团队搞的

这类项目的基本是:转账/交易会收取 2%的利息以及 3%的流动性费用(数据来自Pig),2%的利息直接均匀分发给持币人(也就是rbase或ampl那一套),3%则在达到一定金额后自动卖掉1.5%的Token,然后提供流动性,这样流动性池子将持续变大(该部分流动性权益存放在Token合约中),不能取出。

由于transfer逻辑异常复杂,有各种手续费收取判断(白名单)以及自动提供逻辑性逻辑(超过一定金额),因此gas费较高。猜测rbase死掉可能是由于eth gas过高,而bsc上gas低得多,所以活得很好?

具体参数解释

这里列出一些参数和配置,看完基本能理解动物币这些模式的具体内部逻辑了

它基于的是一种份额概念,所以用户余额是可能变多的,类似于ampl,具体逻辑:


// 单纯的常量,用于计算份额
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);
}

在这里面,还有很多其他可配置的逻辑参数(管理员),以及一些配合理解逻辑的参数,具体见注释:

建议

  1. 可以管理员到时候移交给dao,dao另外搞一个token,然后 1:1 与safemoon 兑换

  2. 允许提取token出来,因为流动性代币等均存放在token合约中

  3. 提供LP奖励,这里要考虑奖励时mint出来的总量怎么管理,以及总量超限问题等,挺复杂逻辑

参考资料

最后更新于