safemoon分红机制原理解析

  • cj
  • 更新于 2021-09-06 10:31
  • 阅读 147

在社区里提问了这个问题,自己做个总结

合约源码

https://cn.etherscan.com/address/0xcd7492db29e2ab436e819b249452ee1bbdf52214#code

基本原理

每一笔转账都会触发分红,但是分红不会触发转账,只是修改一个系数,即修改每个用户的占比。 在别人进行转账时,用户的rOwned不变,系数currentRate变小,实际余额变大。 我觉得需要理解的一点是:在用户转账成功后,还未分红的时候,用户的_rOwned占比即为分红后的占比

举例说明

假设用户所有转账即为分红 _tTotal = 100,_rTotal = 10000 _rOwned[A] = 7000,_rOwned[B] = 2000,_rOwned[C] = 1000 用户B发起转账交易1000,即1000用做被分红。

  1. 常规分红计算

    _rOwned[A] = 70 + 70/90*10 = 700/9

    _rOwned[B] = 10 + 10/90*10 = 100/9

    _rOwned[C] = 10 + 10/90*10 = 100/9

  2. 占比分红

    _rOwned[A] = 7000/9000*100 = 700/9

    _rOwned[B] = 1000/9000*100 = 100/9

    _rOwned[C] = 1000/9000*100 = 100/9

余额核心代码

contract SMI is Context, IERC20, Ownable {
    mapping (address => uint256) private _rOwned; 
    mapping (address => uint256) private _tOwned;

    uint256 private constant MAX = ~uint256(0); //最大值
    uint256 private constant _tTotal = 100000 * 10**6 * 10**9; // 实际总量
    uint256 private _rTotal = (MAX - (MAX % _tTotal)); // 映射的总量

    function balanceOf(address account) public view override returns (uint256) {
        if (_isExcluded[account]) return _tOwned[account]; //不参与分红的用户
        return tokenFromReflection(_rOwned[account]);//参与分红的用户
    }
    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);
    }
    function _getRate() private view returns(uint256) {
        (uint256 rSupply, uint256 tSupply) = _getCurrentSupply();
        return rSupply.div(tSupply);
    }

    function _getCurrentSupply() private view returns(uint256, uint256) {
        uint256 rSupply = _rTotal;
        uint256 tSupply = _tTotal;      
        for (uint256 i = 0; i < _excluded.length; i++) {
            if (_rOwned[_excluded[i]] > rSupply || _tOwned[_excluded[i]] > tSupply) return (_rTotal, _tTotal);
            rSupply = rSupply.sub(_rOwned[_excluded[i]]);
            tSupply = tSupply.sub(_tOwned[_excluded[i]]);
        }
        if (rSupply < _rTotal.div(_tTotal)) return (_rTotal, _tTotal);
        return (rSupply, tSupply);
    }
}
点赞 1
收藏 1
分享

0 条评论

请先 登录 后评论
cj
cj
江湖只有他的大名,没有他的介绍。