最近市場上出現了很多分紅幣,比如最近流行的(BabyDoge, MiniDoge之類的),大概模式都是交易手續費的 x% 按照持有比例分給所有持幣人,今天我們來決議一下背后的代碼實作方式,
第一想法肯定是計算出分紅的手續費之后,按照比例給所有人加上,solidity代碼如下:
// 分紅總金額
uint profit;
// 當前總持幣量
uint totalAmounts;
for (uint i = 0; i < users.length; i++) {
// 給每個用戶分紅
amounts[i] += amounts[i] / totalAmounts * profit;
}
但這樣做會有一個很大的問題:隨著持幣人數過多,每一筆轉賬消耗的計算資源會急速增長,甚至超出交易的單筆上限,
目前分紅類代幣采用了一個很聰明的做法,使用了類似于金融中的通縮概念:“如果貨幣總量減少,每個人手上的貨幣不就變得更值錢的,相當于變相完成了分紅“
接下來我們來看源代碼是怎么實作的
// 存盤用戶的虛擬數量
mapping(address => uint256) private _rOwned;
// 真正的發行量(比如發行了 1w 枚幣,精度為0,_tTotal = 10000)
uint _tTotal;
uint256 private constant MAX = ~uint256(0);
// 最大的一個可以整除 _tTotal 的數,這個數字類似于“虛擬的貨幣總量”
uint _rTotal = (MAX - (MAX % _tTotal));
假設在合約部署時需要把 1w 枚幣發給 owner,代碼如下
constructor() {
_tTotal = 10000;
// 初始化 rTotal
uint256 private constant MAX = ~uint256(0);
uint _rTotal = (MAX - (MAX % _tTotal));
// 把所有的幣發給 owner
_rOwned[owner] = _rTotal;
}
那么此時怎么計算用戶余額呢?我們來看 balanceOf 函式
function balanceOf(address account) public view override returns (uint256) {
uint256 currentRate = _rTotal / _tTotal;
return _rOwned[account] / currentRate;
}
看起來就是先用 虛擬貨幣總量 / 真實貨幣總量 得到一個比例,然后除以這個比例即可拿到真實的余額,
我們再看一下 最重要的transfer 函式是怎么實作的,我們假設分幣比例是 3%
function transfer(address from, address to, uint amount) public {
uint currentRate = _rTotal / _tTotal;
uint rAmount = amount * currentRate;
// 3%的分紅
uint rProfit = amount * currentRate * 3 / 100;
// 轉讓人扣除 100%
_rOwned[from] = _rOwned[from] - rAmount;
// 接收人收到 97%
_rOwned[to] = _rOwned[to] + rAmount * 97 / 100;
// 剩下3%扣除總的虛擬貨幣,這時候所有人的 banlanceOf 函式計算都會按照比例增長
_rTotal = _rTotal - rProfit;
}
不得不說整套體系設計得挺厲害的,雖然存在一定的計算誤差,但大大提高了計算效率,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/307378.html
標籤:區塊鏈
