solidity 分红原理-笔记记录
分红的原理就是分红的那部分token先是整个销毁所以导致所有的人的token都会相对应地增值,数量减少,但我不想增值只想增长数量所以通过除法可以让分母减少分子增加导致每个对应的数量就会上升。
balance就是 b = this account owner number/token/totalsupply
一个简单测试demo
pragma solidity ^0.8.0;
contract test{
// uint256 public constant MAX = ~uint256(0);
// uint256 public constant _tTotal = 10 * 10**6 * 10**9;
// uint256 private _rTotal = (MAX - (MAX % _tTotal));
uint public tT = 1000; //totalsupply
uint public rT = 100000000; //可整除totalsupply的大数,需要超大数,一般是2**256
uint public rOwner ; //owner拥有的token数量,一般是 mapping(address=》uint)
// uint rOwner = 100;
constructor(){
rOwner = rT;//构造函数让owner拥有所有的token,给owner 那个大数的数量
}
//通过这个函数查询余额,都通过计算,msg.sender经过计算 rowner(rT/tT)->可得到tT。
function balance()public view returns(uint256){
uint i = rT/tT;
uint rOwners = rOwner/i;
return rOwners;
}
//transfer函数,i,是大数整除totalsupply的数字
function transfer()public{
uint i = rT/tT;
//rT = rT - (tokenamount * i * 分红份数)
//example rT = rT - (amount * i * 1/100)
rT = rT - (i*30);
//算完整个rT会减小,从而导致i 减小,而balance中rowner/i,因为i减小导致rowner增加
}
}
附上一个类似的项目源码:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
/**
* /$$$$$$$$ /$$ /$$$$$$$ /$$
* |__ $$__/ | $$ | $$__ $$ | $$
* | $$ /$$$$$$ /$$ /$$ /$$$$$$$ /$$$$$$ | $$ \ $$ /$$$$$$ /$$$$$$$
* | $$ /$$__ $$| $$ | $$ /$$_____/|_ $$_/ | $$$$$$$/|____ $$ /$$__ $$
* | $$| $$ \__/| $$ | $$| $$$$$$ | $$ | $$____/ /$$$$$$$| $$ | $$
* | $$| $$ | $$ | $$ \____ $$ | $$ /$$| $$ /$$__ $$| $$ | $$
* | $$| $$ | $$$$$$/ /$$$$$$$/ | $$$$/| $$ | $$$$$$$| $$$$$$$
* |__/|__/ \______/ |_______/ \___/ |__/ \_______/ \_______/
*/
contract TrustPad is Context, IERC20, Ownable {
using Address for address;
mapping(address => uint256) private _rOwned;
mapping(address => uint256) private _tOwned;
mapping(address => mapping(address => uint256)) private _allowances;
mapping(address => bool) private _isExcluded;
address[] private _excluded;
uint256 private constant MAX = ~uint256(0);
uint256 private constant _tTotal = 100 * (10 ** 6) * (10 ** 9);
uint256 private _rTotal = (MAX - (MAX % _tTotal));
uint256 private _tFeeTotal;
uint256 private _tFeePercent = 2; //
mapping(address => bool) private _isFeeless; //
string private _name = 'TrustPad';
string private _symbol = 'TPAD';
uint8 private _decimals = 9;
event MarkedFeeless(address indexed account, bool isFeeless);
constructor () {
_rOwned[_msgSender()] = _rTotal;
_isFeeless[_msgSender()] = true;
emit Transfer(address(0), _msgSender(), _tTotal);
emit MarkedFeeless(_msgSender(), true);
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
function totalSupply() public pure override returns (uint256) {
return _tTotal;
}
function balanceOf(address account) external view override returns (uint256) {
if (_isExcluded[account]) return _tOwned[account];
return tokenFromReflection(_rOwned[account]);
}
function transfer(address recipient, uint256 amount) external override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) external view override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) external override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
_approve(sender, _msgSender(), currentAllowance - amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
return true;
}
function isExcluded(address account) public view returns (bool) {
return _isExcluded[account];
}
function isFeeless(address account) public view returns (bool) {
return _isFeeless[account];
}
function totalFees() public view returns (uint256) {
return _tFeeTotal;
}
function reflect(uint256 tAmount) external {
address sender = _msgSender();
require(!_isExcluded[sender], "Excluded addresses cannot call this function");
(uint256 rAmount,,,,) = _getValues(tAmount);
_rOwned[sender] = _rOwned[sender] - rAmount;
_rTotal = _rTotal - rAmount;
_tFeeTotal = _tFeeTotal + tAmount;
}
function reflectionFromToken(uint256 tAmount, bool deductTransferFee) public view returns (uint256) {
require(tAmount <= _tTotal, "Amount must be less than supply");
if (!deductTransferFee) {
(uint256 rAmount,,,,) = _getValues(tAmount);
return rAmount;
} else {
(,uint256 rTransferAmount,,,) = _getValues(tAmount);
return rTransferAmount;
}
}
function tokenFromReflection(uint256 rAmount) public view returns (uint256) {
require(rAmount <= _rTotal, "Amount must be less than total reflections");
uint256 currentRate = _getRate();
return rAmount / currentRate;
}
function excludeAccount(address account) external onlyOwner() {
require(account != address(this), "Cannot exclude self contract");
require(!_isExcluded[account], "Account is already excluded");
if (_rOwned[account] > 0) {
_tOwned[account] = tokenFromReflection(_rOwned[account]);
}
_isExcluded[account] = true;
_excluded.push(account);
}
function includeAccount(address account) external onlyOwner() {
require(_isExcluded[account], "Account is already included");
uint length = _excluded.length;
for (uint256 i = 0; i < length; i++) {
if (_excluded[i] == account) {
_excluded[i] = _excluded[_excluded.length - 1];
_tOwned[account] = 0;
_isExcluded[account] = false;
_excluded.pop();
break;
}
}
}
function setFeeless(address account, bool isFeeless_) external onlyOwner() {
_isFeeless[account] = isFeeless_;
emit MarkedFeeless(account, isFeeless_);
}
function _approve(address owner, address spender, uint256 amount) private {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _transfer(address sender, address recipient, uint256 amount) private {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
require(amount > 0, "Transfer amount must be greater than zero");
if (_isExcluded[sender] && !_isExcluded[recipient]) {
_transferFromExcluded(sender, recipient, amount);
} else if (!_isExcluded[sender] && _isExcluded[recipient]) {
_transferToExcluded(sender, recipient, amount);
} else if (!_isExcluded[sender] && !_isExcluded[recipient]) {
_transferStandard(sender, recipient, amount);
} else if (_isExcluded[sender] && _isExcluded[recipient]) {
_transferBothExcluded(sender, recipient, amount);
} else {
_transferStandard(sender, recipient, amount);
}
}
function _transferStandard(address sender, address recipient, uint256 tAmount) private {
bool isFeelessTx = _isFeeless[sender] || _isFeeless[recipient];
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee) = _getValues(tAmount, isFeelessTx);
_rOwned[sender] = _rOwned[sender] - rAmount;
_rOwned[recipient] = _rOwned[recipient] + rTransferAmount;
_reflectFee(rFee, tFee);
emit Transfer(sender, recipient, tTransferAmount);
}
function _transferToExcluded(address sender, address recipient, uint256 tAmount) private {
bool isFeelessTx = _isFeeless[sender] || _isFeeless[recipient];
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee) = _getValues(tAmount, isFeelessTx);
_rOwned[sender] = _rOwned[sender] - rAmount;
_tOwned[recipient] = _tOwned[recipient] + tTransferAmount;
_rOwned[recipient] = _rOwned[recipient] + rTransferAmount;
_reflectFee(rFee, tFee);
emit Transfer(sender, recipient, tTransferAmount);
}
function _transferFromExcluded(address sender, address recipient, uint256 tAmount) private {
bool isFeelessTx = _isFeeless[sender] || _isFeeless[recipient];
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee) = _getValues(tAmount, isFeelessTx);
_tOwned[sender] = _tOwned[sender] - tAmount;
_rOwned[sender] = _rOwned[sender] - rAmount;
_rOwned[recipient] = _rOwned[recipient] + rTransferAmount;
_reflectFee(rFee, tFee);
emit Transfer(sender, recipient, tTransferAmount);
}
function _transferBothExcluded(address sender, address recipient, uint256 tAmount) private {
bool isFeelessTx = _isFeeless[sender] || _isFeeless[recipient];
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee) = _getValues(tAmount, isFeelessTx);
_tOwned[sender] = _tOwned[sender] - tAmount;
_rOwned[sender] = _rOwned[sender] - rAmount;
_tOwned[recipient] = _tOwned[recipient] + tTransferAmount;
_rOwned[recipient] = _rOwned[recipient] + rTransferAmount;
_reflectFee(rFee, tFee);
emit Transfer(sender, recipient, tTransferAmount);
}
function _reflectFee(uint256 rFee, uint256 tFee) private {
_rTotal = _rTotal - rFee;
_tFeeTotal = _tFeeTotal + tFee;
}
function _getValues(uint256 tAmount) private view returns (uint256, uint256, uint256, uint256, uint256) {
return _getValues(tAmount, false);
}
function _getValues(uint256 tAmount, bool isFeeless_) private view returns (uint256, uint256, uint256, uint256, uint256) {
(uint256 tTransferAmount, uint256 tFee) = _getTValues(tAmount, isFeeless_);
uint256 currentRate = _getRate();
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee) = _getRValues(tAmount, tFee, currentRate);
return (rAmount, rTransferAmount, rFee, tTransferAmount, tFee);
}
function _getTValues(uint256 tAmount, bool isFeeless_) private view returns (uint256, uint256) {
if (isFeeless_) {
return (tAmount, 0);
}
uint256 tFee = (tAmount * _tFeePercent) / 100;
uint256 tTransferAmount = tAmount - tFee;
return (tTransferAmount, tFee);
}
function _getRValues(uint256 tAmount, uint256 tFee, uint256 currentRate) private pure returns (uint256, uint256, uint256) {
uint256 rAmount = tAmount * currentRate;
uint256 rFee = tFee * currentRate;
uint256 rTransferAmount = rAmount - rFee;
return (rAmount, rTransferAmount, rFee);
}
function _getRate() private view returns (uint256) {
(uint256 rSupply, uint256 tSupply) = _getCurrentSupply();
return rSupply / tSupply;
}
function _getCurrentSupply() private view returns (uint256, uint256) {
uint256 rSupply = _rTotal;
uint256 tSupply = _tTotal;
uint length = _excluded.length;
for (uint256 i = 0; i < length; i++) {
if (_rOwned[_excluded[i]] > rSupply || _tOwned[_excluded[i]] > tSupply) return (_rTotal, _tTotal);
rSupply = rSupply - _rOwned[_excluded[i]];
tSupply = tSupply - _tOwned[_excluded[i]];
}
if (rSupply < _rTotal / _tTotal) return (_rTotal, _tTotal);
return (rSupply, tSupply);
}
function setFeePercent(uint256 fee) external onlyOwner {
require(fee >= 1, 'Fee is too small');
require(fee <= 10, 'Fee is too big');
_tFeePercent = fee;
}
}
有个项目白皮书 的详解:https://www.keepandshare.com/doc15/24269/reflect-technical-paper-pdf-822k?da=y