
DeFi概念介绍(三)——无常损失和滑点
上篇文章我们讲了AMM的原理,并在最后提到了无常损失这个概念。今天这篇文章就来详细介绍无常损失和滑点这两个概念。无常损失当你成为一个做交易流动池添加者(又称做市商、矿工)时,相当于是和所有交易者做一个对手盘,如果所有交易者的盈亏加在一起还是盈利状态,那这部分的利润就来自于每个做市商的无常损失。 同时无常损失不是永久性的,价格经历短暂下跌后又重新恢复,收益也会修正。 那么如何计算无常损失呢? 还是先列出AMM的核心公式:K = A * B 假设以BNB和BUSD为例:Cbnb - 池中当前BNB 的数量 为上式中的ACbusd - 池中当前BUSD 的数量 为上式中的BPbnb - bnb当前价格Pbusd - busd当前价格 恒定为1u 可省略当K恒定时,我们可以得到任何时刻池中的BNB和BUSD数量真实场景假如,我们在 1 BNB = 500 BUSD 的时候,组了一组 LP 。我们拿出了 20 个 BNB 和 10000 个 BUSD 进行 LP 流动性提供代币兑换。此时我们得到了这几个变量:并且,我们保证此时的 K 也是后续所有情况下的常数 K,即组完 LP 代币后即时生...

Gitcoin女巫检测方案Top1解读及思考
GITCOIN在两个月前举办了 OpenData 社区黑客马拉松!其中公布了三个重点领域,分别是: 女巫检测、捐款激励措施优化分析、Dune高效分析,其结果也于近日公布。 相信大家最关心的应该是女巫问题,因为今年在OP和APT的刺激下,出现了人人羡慕撸毛党,人人皆是撸毛党的盛况。 今天对女巫检测的第一名开源方案结合自身理解,进行技术向的解读,并在文末给出自己对于女巫检测的一些个人思考。相信看完这篇文章,无论是项目方还是交互者都能有所收获。 注:本文不代表官方观点,仅为个人兴趣解读。 剧透,本文较长,涉及很多技术分析,没耐心的可以直接跳转文末浏览本文总结与个人思考。由于出题者是gitcoin,其主要交互场景为捐赠。但内在逻辑在其他的场景下同样适用(transfer、mint等动作),以下将与项目方进行交互的操作统称为项目交互。方案一:批量转移和交互女巫攻击本质上是用户将资金分散到多个地址,操纵这些地址与项目方合约进行交互的过程。 那么在这个过程中则可以将整个过程拆分两个部分,分别是 批量资金转移和合约批量交互。1.1 批量转账检测选择数据批量转账最简单的就是通过智能合约的方式进行,...
零知识证明和Layer2简介
1、零知识证明简单介绍零知识证明是一方(证明者)向另一方(检验者)在不透露具体内容的条件下证明某命题的方法。 举例: 两个富翁A和B相遇,两人的资产都在1-10亿之间,要如何在不告诉对方自己具体财富的情况下,得出对方是否比自己有钱?区块链中的零知识证明:其实大家可能会疑惑,为什么会用到零知识证明,那其实。在区块链机制中,想要去证明自己有存储某个东西的时候。他其实是不会把这个东西全部发给你来证明?比如说存储了一部电影我,可能不会把整个电影发给你了他,会有一种证明机制去,证明里面的某一块或者是某个东西他是有的,通过提交某个证明去给到系统,系统知道你有存这个东西这种就是其实就是零知识证明的一种,就是不公布具体内容,但是证明某个事情。例如银行贷款必须提交资产证明,通过零知识,无需提供银行房本,住址这些资料。2、Layer2简单介绍起源Layer2的诞生是为了解决以太坊主网拥堵及昂贵的问题,在Eth2.0完成之前保持住以太坊上生态霸主的地位。 广泛层面上,Layer2包含所有和以太坊主链有桥接的项目,包含像Polygon这类几乎独立的区块链; 狭义层面,指的是指以以太坊主网作为最终状态记录...
<100 subscribers
代币通缩模型最早起源 meme币Pig 发扬光大在safemoon ,有早期用户0.2eth变6700万美元的神话。
道理比较简单,就是币随交易,越来越少,从而导致代币越来越有价值。 而体现合约中,查阅后却没有一个很好的解释,趁着最近在看合约代码,试图做一些浅显的理解: 我以一个实现通缩的Token catgirl 为例
首先先明确两个uint类型私有变量:_tTotal 和 _rTotal
_tTotal 就是 我们发行的总币量
_rTotal 则是 一个内部币总量 通过减少该币数量 进行通缩分红 使得账号上代币数量提升
其中 _rTotal >> _tTotal
uint256 private constant MAX = ~uint256(0);
//对外展示的币总量,为100000 * 10**12 * 10**9,
uint256 private _tTotal = 100000 * 10**12 * 10**9;
//是内部实际的币总量,为2^256-(2^256%_tTotal)
uint256 private _rTotal = (MAX - (MAX % _tTotal));
如果你对银行业务比较了解,你应该知道一个名词叫做存款准备金率。其核心就是 中央银行要求的存款准备金占其存款总额的比例就是存款准备金率(deposit-reserve ratio)。
_rTotal and _tTotal类似于 银行存款,但是相反的是。这里 _ rTotal 为中央银行的总代币供应量, _tTotal是你口袋中+存在银行里的代币数量。rTotal大于_tTotal,为什么会大于,下面会将,现在只需要记住_rTotal和_tTotal的类比概念即可。 函数 _getRate() 则表示_rTotal/_tTotal,类似于上面的存款准备金率概念。
核心原理:就是在_tTotal 除扣除手续费外总量不变的情况下,_rTotal每次交易扣除2倍手续费来进行通缩,从而提升所有持有相同t币数量的t币价值。
下面我根据下图来进行讲解

tTotal 初始化为 10000 外部显示币总数量
rTotal 初始化为 127366483000000 = MAX-(MAX%tTotal) 注 MAX = uint256最大数值表示
rate rTotal/tTotal 的值
mapping (address => uint256) rOwned 内部一个拥有r币地址=> r数量的映射
mapping (address => uint256) tAmount 内部一个拥有t币地址=> r数量的映射
tAmount 一个地址想购买t币的数量
FeeRate 只要转账就将转账数量的FeeRate 直接燃烧销毁 这里我们取10%
rTransferAmount 转账对方收到的r币 = rAmount - rfee
balanceOf(地址X) 地址X的外部显示t币余额
地址A 代表发币地址 初始tTotal = 10000 内部: tTotal[A] = 10000 rTotal[A] = 127366483000000 外部显示:balanceOf(A) = 10000
此刻
rTotal = 127366483000000
tTotal = 10000
rate = rTotal / tTotal = 12736648300
假设用户A向用户B转账100个 t币 tAmount = 100
故:
rAmount = tAmount * rate = 1273664830000
tfee = 10%*tAmount = 10
rfee = tfee *rate = 127366483000
rTransferAmount = rAmount - rfee = 1146298347000
交易结束后rTotal再销毁 一份rfee 并且记录等值的tfree
调用safemoon中的reflectFee() 方法 从而改变rate
此时:
rate = rTotal / tTotal = 12736648300
rTotal = rTotal-rfee(转账消耗) - rfee(系统销毁r币) = 127111750034000
rOwned[A] -= rAmount = 127366483000000 - 1273664830000 = 126092818170000
rOwned[B] += rTransferAmount (扣除税)= 1146298347000
tOwned[A] -= 10000-100 = 9900
tOwned[B] += rTransferAmount/rate = 90
balanceOf(A) = rOwned[A] /rate = 9900 balanceOf(B) = rOwned[B] /rate = 90
此刻
rTotal = 127111750034000
tTotal = 9990
rate = rTotal / tTotal = 12723898902.302301 此时 小于第一次交易的rate
假设用户A向用户C转账100个 t币 tAmount = 100
故:
rAmount = tAmount * rate = 1272389890230
tfee = 10%*tAmount = 10
rfee = tfee *rate = 127238989023
rTransferAmount = rAmount - rfee = 1145150901207.207
此时:
rOwned[A] -= rAmount
rOwned[C] += rTransferAmount (扣除税)
tOwned[A] -= tAmount
tOwned[C] += tAmount - tfee
交易结束后rTotal再销毁 一份rfee 并且记录等值的tfree
调用safemoon中的reflectFee() 方法 从而改变rate
此时指标:
rate = rTotal / tTotal = 12723898902.302301
rTotal = rTotal-rfee(转账消耗) - rfee(系统销毁r币) = 126857272055954
rOwned[A] -= rAmount = 126092818170000 - 1272389890230 = 124820428279770
rOwned[C] += rTransferAmount (扣除税)= 1145150901207.207
tOwned[A] -= 9900-100 = 9800
tOwned[C] += rTransferAmount/rate = 90
balanceOf(A) = rOwned[A] /rate = 9809.919839679378 balanceOf(B) = rOwned[B] /rate =90.09018036072145 balanceOf(C) = rOwned[C] /rate = 90
balanceOf() 函数是由 rOwned[] 和rate 决定,和tOwned[]没有关系。
可以发现此时 B账户的r币没变,但是balanceOf 得到数量余额变多了,这就是通缩燃烧r币导致的代币变多,从而价值提升。
第一步 设置变量
// 用户内部持有的实际币数量,可以看成是每个用户拥有的盘子数量
mapping (address => uint256) private _rOwned;
// 只用于非分红用户的转账,可以看成是一个帮助类
mapping (address => uint256) private _tOwned;
// 类似于ERC20的allowance,指用户授权某些账户的可使用额度
mapping (address => mapping (address => uint256)) private _allowances;
// 账户白名单,用来判断是否需要转账手续费
mapping (address => bool) private _isExcludedFromFee;
// 账户通缩名单标志位,用来判断是否参与通缩分红 true代表排除通缩之外 false 代表进行通缩奖励 默认全员通缩
mapping (address => bool) private _isExcluded;
// 巨鲸黑名单标志位 购买超过总量的1%
mapping (address => bool) public _isExcludedFromAntiWhale;
// 拥有token标志位
mapping (address => bool) private _AddressExists;
// 地址数组
address[] private _addressList;
// 不计入通缩address记录 只有_isExcluded[address]=true的 才加入
address[] private _excluded;
uint256 private constant MAX = ~uint256(0);
//对外展示的币总量,为100000 * 10**12 * 10**9,可以看出是总的蛋糕
uint256 private _tTotal = 100000 * 10**12 * 10**9;
//是内部实际的币总量,为2^256-(2^256%_tTotal),是一个很大的数,可以看出是盘子的数量
uint256 private _rTotal = (MAX - (MAX % _tTotal));
// 收取的手续费,可以看成是打碎了多少盘子,但是不影响总蛋糕_tTotal
uint256 private _tFeeTotal;
// 代币名称
string private _name = "CatGirl";
// 代币符号
string private _symbol = "CATGIRL";
// 代币精度
uint8 private _decimals = 9;
// 转账收取的手续费,这部分手续费会直接销毁,进而导致_rTotal减少,也就是总量的通缩。
uint256 public _taxFee = 4;
// 上一次设置的手续费,是个历史记录
uint256 private _previousTaxFee = _taxFee;
// 转账收取的流动性手续费,这部分手续费会添加到uniswap的交易对里
uint256 public _liquidityFee = 1;
// 上一次设置的手续费,是个历史记录
uint256 private _previousLiquidityFee = _liquidityFee;
// 彩票税
uint256 public _lottoFee = 2;
uint256 private _previousLottoFee = _lottoFee;
// 开发者税
uint256 public _devFee = 1;
uint256 private _previousDevFee = _devFee;
// uniswap的路由器,用于添加流动性
IUniswapV2Router02 public uniswapV2Router;
// 在uniswap的创建的catgirl-bnb交易对
address public uniswapV2Pair;
// 用于lockTheSwap这个modifier,用来加锁的
bool inSwapAndLiquify;
bool inLotteryDraw;
代码核心四个方法:
_getRate 获取当前的rSupply/tSupply 的 比率
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);
可以看到用的是
rSupply = _rTotal - 所有被排除通缩账号的r数量
tSupply = _tTotal - 所有被排除通缩账号的t数量
_getRValues 根据转移的 tAmount 计算 对应的rAmount和扣除各种费用的rTransferAmount 和扣除总费用rFee
function _getRValues(TData memory _data) private pure returns (uint256, uint256, uint256) {
uint256 rAmount = _data.tAmount.mul(_data.currentRate);
uint256 rFee = _data.tFee.mul(_data.currentRate);
uint256 rLiquidity = _data.tLiquidity.mul(_data.currentRate);
uint256 rLotto = _data.tLotto.mul(_data.currentRate);
uint256 rDev = _data.tDev.mul(_data.currentRate);
uint256 rTransferAmount = rAmount.sub(rFee).sub(rLiquidity).sub(rLotto).sub(rDev);
return (rAmount, rTransferAmount, rFee);
得到结果 rAmount = tAmount* currentRate;
_reflectFee(rFee, tFee); 主动通缩r币总量 并将对应的tFee计数保存
receive() external payable {}
function _reflectFee(uint256 rFee, uint256 tFee) private {
_rTotal = _rTotal.sub(rFee);
_tFeeTotal = _tFeeTotal.add(tFee);
}
每次交易都会调用该方法,通缩减少rFee个r币 _rTotal = _rTotal.sub(rFee);
function balanceOf(address account) public view override returns (uint256) {
// 如果account在非通缩分红名单中 直接返回_tOwned[account] 否则进行通缩计算新值
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);
}
balanceOf(address) = _rOwned[account].div(currentRate)
https://its201.com/article/zgsdzczh/116706584 https://reflect-contract-doc.netlify.app/ https://ethereum.stackexchange.com/questions/98622/binance-smart-chain-tokens-what-are-ttotal-rtotal-tsupply-rsupply-rowned-t
代币通缩模型最早起源 meme币Pig 发扬光大在safemoon ,有早期用户0.2eth变6700万美元的神话。
道理比较简单,就是币随交易,越来越少,从而导致代币越来越有价值。 而体现合约中,查阅后却没有一个很好的解释,趁着最近在看合约代码,试图做一些浅显的理解: 我以一个实现通缩的Token catgirl 为例
首先先明确两个uint类型私有变量:_tTotal 和 _rTotal
_tTotal 就是 我们发行的总币量
_rTotal 则是 一个内部币总量 通过减少该币数量 进行通缩分红 使得账号上代币数量提升
其中 _rTotal >> _tTotal
uint256 private constant MAX = ~uint256(0);
//对外展示的币总量,为100000 * 10**12 * 10**9,
uint256 private _tTotal = 100000 * 10**12 * 10**9;
//是内部实际的币总量,为2^256-(2^256%_tTotal)
uint256 private _rTotal = (MAX - (MAX % _tTotal));
如果你对银行业务比较了解,你应该知道一个名词叫做存款准备金率。其核心就是 中央银行要求的存款准备金占其存款总额的比例就是存款准备金率(deposit-reserve ratio)。
_rTotal and _tTotal类似于 银行存款,但是相反的是。这里 _ rTotal 为中央银行的总代币供应量, _tTotal是你口袋中+存在银行里的代币数量。rTotal大于_tTotal,为什么会大于,下面会将,现在只需要记住_rTotal和_tTotal的类比概念即可。 函数 _getRate() 则表示_rTotal/_tTotal,类似于上面的存款准备金率概念。
核心原理:就是在_tTotal 除扣除手续费外总量不变的情况下,_rTotal每次交易扣除2倍手续费来进行通缩,从而提升所有持有相同t币数量的t币价值。
下面我根据下图来进行讲解

tTotal 初始化为 10000 外部显示币总数量
rTotal 初始化为 127366483000000 = MAX-(MAX%tTotal) 注 MAX = uint256最大数值表示
rate rTotal/tTotal 的值
mapping (address => uint256) rOwned 内部一个拥有r币地址=> r数量的映射
mapping (address => uint256) tAmount 内部一个拥有t币地址=> r数量的映射
tAmount 一个地址想购买t币的数量
FeeRate 只要转账就将转账数量的FeeRate 直接燃烧销毁 这里我们取10%
rTransferAmount 转账对方收到的r币 = rAmount - rfee
balanceOf(地址X) 地址X的外部显示t币余额
地址A 代表发币地址 初始tTotal = 10000 内部: tTotal[A] = 10000 rTotal[A] = 127366483000000 外部显示:balanceOf(A) = 10000
此刻
rTotal = 127366483000000
tTotal = 10000
rate = rTotal / tTotal = 12736648300
假设用户A向用户B转账100个 t币 tAmount = 100
故:
rAmount = tAmount * rate = 1273664830000
tfee = 10%*tAmount = 10
rfee = tfee *rate = 127366483000
rTransferAmount = rAmount - rfee = 1146298347000
交易结束后rTotal再销毁 一份rfee 并且记录等值的tfree
调用safemoon中的reflectFee() 方法 从而改变rate
此时:
rate = rTotal / tTotal = 12736648300
rTotal = rTotal-rfee(转账消耗) - rfee(系统销毁r币) = 127111750034000
rOwned[A] -= rAmount = 127366483000000 - 1273664830000 = 126092818170000
rOwned[B] += rTransferAmount (扣除税)= 1146298347000
tOwned[A] -= 10000-100 = 9900
tOwned[B] += rTransferAmount/rate = 90
balanceOf(A) = rOwned[A] /rate = 9900 balanceOf(B) = rOwned[B] /rate = 90
此刻
rTotal = 127111750034000
tTotal = 9990
rate = rTotal / tTotal = 12723898902.302301 此时 小于第一次交易的rate
假设用户A向用户C转账100个 t币 tAmount = 100
故:
rAmount = tAmount * rate = 1272389890230
tfee = 10%*tAmount = 10
rfee = tfee *rate = 127238989023
rTransferAmount = rAmount - rfee = 1145150901207.207
此时:
rOwned[A] -= rAmount
rOwned[C] += rTransferAmount (扣除税)
tOwned[A] -= tAmount
tOwned[C] += tAmount - tfee
交易结束后rTotal再销毁 一份rfee 并且记录等值的tfree
调用safemoon中的reflectFee() 方法 从而改变rate
此时指标:
rate = rTotal / tTotal = 12723898902.302301
rTotal = rTotal-rfee(转账消耗) - rfee(系统销毁r币) = 126857272055954
rOwned[A] -= rAmount = 126092818170000 - 1272389890230 = 124820428279770
rOwned[C] += rTransferAmount (扣除税)= 1145150901207.207
tOwned[A] -= 9900-100 = 9800
tOwned[C] += rTransferAmount/rate = 90
balanceOf(A) = rOwned[A] /rate = 9809.919839679378 balanceOf(B) = rOwned[B] /rate =90.09018036072145 balanceOf(C) = rOwned[C] /rate = 90
balanceOf() 函数是由 rOwned[] 和rate 决定,和tOwned[]没有关系。
可以发现此时 B账户的r币没变,但是balanceOf 得到数量余额变多了,这就是通缩燃烧r币导致的代币变多,从而价值提升。
第一步 设置变量
// 用户内部持有的实际币数量,可以看成是每个用户拥有的盘子数量
mapping (address => uint256) private _rOwned;
// 只用于非分红用户的转账,可以看成是一个帮助类
mapping (address => uint256) private _tOwned;
// 类似于ERC20的allowance,指用户授权某些账户的可使用额度
mapping (address => mapping (address => uint256)) private _allowances;
// 账户白名单,用来判断是否需要转账手续费
mapping (address => bool) private _isExcludedFromFee;
// 账户通缩名单标志位,用来判断是否参与通缩分红 true代表排除通缩之外 false 代表进行通缩奖励 默认全员通缩
mapping (address => bool) private _isExcluded;
// 巨鲸黑名单标志位 购买超过总量的1%
mapping (address => bool) public _isExcludedFromAntiWhale;
// 拥有token标志位
mapping (address => bool) private _AddressExists;
// 地址数组
address[] private _addressList;
// 不计入通缩address记录 只有_isExcluded[address]=true的 才加入
address[] private _excluded;
uint256 private constant MAX = ~uint256(0);
//对外展示的币总量,为100000 * 10**12 * 10**9,可以看出是总的蛋糕
uint256 private _tTotal = 100000 * 10**12 * 10**9;
//是内部实际的币总量,为2^256-(2^256%_tTotal),是一个很大的数,可以看出是盘子的数量
uint256 private _rTotal = (MAX - (MAX % _tTotal));
// 收取的手续费,可以看成是打碎了多少盘子,但是不影响总蛋糕_tTotal
uint256 private _tFeeTotal;
// 代币名称
string private _name = "CatGirl";
// 代币符号
string private _symbol = "CATGIRL";
// 代币精度
uint8 private _decimals = 9;
// 转账收取的手续费,这部分手续费会直接销毁,进而导致_rTotal减少,也就是总量的通缩。
uint256 public _taxFee = 4;
// 上一次设置的手续费,是个历史记录
uint256 private _previousTaxFee = _taxFee;
// 转账收取的流动性手续费,这部分手续费会添加到uniswap的交易对里
uint256 public _liquidityFee = 1;
// 上一次设置的手续费,是个历史记录
uint256 private _previousLiquidityFee = _liquidityFee;
// 彩票税
uint256 public _lottoFee = 2;
uint256 private _previousLottoFee = _lottoFee;
// 开发者税
uint256 public _devFee = 1;
uint256 private _previousDevFee = _devFee;
// uniswap的路由器,用于添加流动性
IUniswapV2Router02 public uniswapV2Router;
// 在uniswap的创建的catgirl-bnb交易对
address public uniswapV2Pair;
// 用于lockTheSwap这个modifier,用来加锁的
bool inSwapAndLiquify;
bool inLotteryDraw;
代码核心四个方法:
_getRate 获取当前的rSupply/tSupply 的 比率
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);
可以看到用的是
rSupply = _rTotal - 所有被排除通缩账号的r数量
tSupply = _tTotal - 所有被排除通缩账号的t数量
_getRValues 根据转移的 tAmount 计算 对应的rAmount和扣除各种费用的rTransferAmount 和扣除总费用rFee
function _getRValues(TData memory _data) private pure returns (uint256, uint256, uint256) {
uint256 rAmount = _data.tAmount.mul(_data.currentRate);
uint256 rFee = _data.tFee.mul(_data.currentRate);
uint256 rLiquidity = _data.tLiquidity.mul(_data.currentRate);
uint256 rLotto = _data.tLotto.mul(_data.currentRate);
uint256 rDev = _data.tDev.mul(_data.currentRate);
uint256 rTransferAmount = rAmount.sub(rFee).sub(rLiquidity).sub(rLotto).sub(rDev);
return (rAmount, rTransferAmount, rFee);
得到结果 rAmount = tAmount* currentRate;
_reflectFee(rFee, tFee); 主动通缩r币总量 并将对应的tFee计数保存
receive() external payable {}
function _reflectFee(uint256 rFee, uint256 tFee) private {
_rTotal = _rTotal.sub(rFee);
_tFeeTotal = _tFeeTotal.add(tFee);
}
每次交易都会调用该方法,通缩减少rFee个r币 _rTotal = _rTotal.sub(rFee);
function balanceOf(address account) public view override returns (uint256) {
// 如果account在非通缩分红名单中 直接返回_tOwned[account] 否则进行通缩计算新值
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);
}
balanceOf(address) = _rOwned[account].div(currentRate)
https://its201.com/article/zgsdzczh/116706584 https://reflect-contract-doc.netlify.app/ https://ethereum.stackexchange.com/questions/98622/binance-smart-chain-tokens-what-are-ttotal-rtotal-tsupply-rsupply-rowned-t

DeFi概念介绍(三)——无常损失和滑点
上篇文章我们讲了AMM的原理,并在最后提到了无常损失这个概念。今天这篇文章就来详细介绍无常损失和滑点这两个概念。无常损失当你成为一个做交易流动池添加者(又称做市商、矿工)时,相当于是和所有交易者做一个对手盘,如果所有交易者的盈亏加在一起还是盈利状态,那这部分的利润就来自于每个做市商的无常损失。 同时无常损失不是永久性的,价格经历短暂下跌后又重新恢复,收益也会修正。 那么如何计算无常损失呢? 还是先列出AMM的核心公式:K = A * B 假设以BNB和BUSD为例:Cbnb - 池中当前BNB 的数量 为上式中的ACbusd - 池中当前BUSD 的数量 为上式中的BPbnb - bnb当前价格Pbusd - busd当前价格 恒定为1u 可省略当K恒定时,我们可以得到任何时刻池中的BNB和BUSD数量真实场景假如,我们在 1 BNB = 500 BUSD 的时候,组了一组 LP 。我们拿出了 20 个 BNB 和 10000 个 BUSD 进行 LP 流动性提供代币兑换。此时我们得到了这几个变量:并且,我们保证此时的 K 也是后续所有情况下的常数 K,即组完 LP 代币后即时生...

Gitcoin女巫检测方案Top1解读及思考
GITCOIN在两个月前举办了 OpenData 社区黑客马拉松!其中公布了三个重点领域,分别是: 女巫检测、捐款激励措施优化分析、Dune高效分析,其结果也于近日公布。 相信大家最关心的应该是女巫问题,因为今年在OP和APT的刺激下,出现了人人羡慕撸毛党,人人皆是撸毛党的盛况。 今天对女巫检测的第一名开源方案结合自身理解,进行技术向的解读,并在文末给出自己对于女巫检测的一些个人思考。相信看完这篇文章,无论是项目方还是交互者都能有所收获。 注:本文不代表官方观点,仅为个人兴趣解读。 剧透,本文较长,涉及很多技术分析,没耐心的可以直接跳转文末浏览本文总结与个人思考。由于出题者是gitcoin,其主要交互场景为捐赠。但内在逻辑在其他的场景下同样适用(transfer、mint等动作),以下将与项目方进行交互的操作统称为项目交互。方案一:批量转移和交互女巫攻击本质上是用户将资金分散到多个地址,操纵这些地址与项目方合约进行交互的过程。 那么在这个过程中则可以将整个过程拆分两个部分,分别是 批量资金转移和合约批量交互。1.1 批量转账检测选择数据批量转账最简单的就是通过智能合约的方式进行,...
零知识证明和Layer2简介
1、零知识证明简单介绍零知识证明是一方(证明者)向另一方(检验者)在不透露具体内容的条件下证明某命题的方法。 举例: 两个富翁A和B相遇,两人的资产都在1-10亿之间,要如何在不告诉对方自己具体财富的情况下,得出对方是否比自己有钱?区块链中的零知识证明:其实大家可能会疑惑,为什么会用到零知识证明,那其实。在区块链机制中,想要去证明自己有存储某个东西的时候。他其实是不会把这个东西全部发给你来证明?比如说存储了一部电影我,可能不会把整个电影发给你了他,会有一种证明机制去,证明里面的某一块或者是某个东西他是有的,通过提交某个证明去给到系统,系统知道你有存这个东西这种就是其实就是零知识证明的一种,就是不公布具体内容,但是证明某个事情。例如银行贷款必须提交资产证明,通过零知识,无需提供银行房本,住址这些资料。2、Layer2简单介绍起源Layer2的诞生是为了解决以太坊主网拥堵及昂贵的问题,在Eth2.0完成之前保持住以太坊上生态霸主的地位。 广泛层面上,Layer2包含所有和以太坊主链有桥接的项目,包含像Polygon这类几乎独立的区块链; 狭义层面,指的是指以以太坊主网作为最终状态记录...
Share Dialog
Share Dialog
No comments yet