概要
书接上文,上文介绍了uniswap的mint铸造函数源码,这一章继续介绍 burn函数(销毁) 。
burn
burn销毁函数和mint铸造函数可以说正好是相反的,mint是添加流动性,而burn是销毁流动性,对应的用户操作是LP 提供者的提现。
注意调用此操作前,用户应该先归还流动性token给 pair合约, 然后在同一笔交易中调用此函数,此函数在逻辑中根据转入的 LP token计算应该归还给用户的对应比例的 tokenA和 tokenB, 并操作打款给用户。
源码解析
1行: 入参为提现(撤销流动性)用户的地址。出参为此函数根据用户转入的LP token计算并转出的两个token的数量。
2~4行: 用临时stack变量接收storage变量,用于接下来的计算,这样省gas。
5~6行: 通过ERC20标准查询余额的函数获取合约当前持有的两个token的余额。
7行: 用于在当前交易中,调用当前函数前转入的LP token数量查询。
9行: 如果uniswap项目方设置了收税地址,uniswap会通过计算恒定成绩差值的方式收取1/6的交易手续费。这里的算法细节会在下面展开讲。
11~12行: 通过计算转入本合约的流动性占总LP token的比值计算可以取出的两种token数量。
14行:销毁本次交易转入的 LP token。
15~16行:转出打款。
17~18行:查看转出后本合约最新的两种代币余额。
20行:更新两种代币的reserve为最新余额,并更新作为预言机的两个币种的价格累计。
21行: 如果 feeOn地址设置了(即uniswap项目方开始收取1/6 交易手续费了),kLast就会更新为最新的两种token数量的平方根。这里的kLast需要展开讲一下。kLast的作用就是为了uniswap收取交易手续费计算使用的,kLast只有在流动性变化的时候(铸造和销毁)调用,这样是为了累计收取交易手续费,节约gas。
_mintFee
收取0.05%的交易手续费函数。目前为止uniswap还没打开此开关, 函数逻辑没用到。如果将来设置了,并不会影响用户的交易手续费(依然是0.3%),只是会分走 LP provider 0.3%中的1/6,即整笔交易手续费的万分之五。只有铸造和销毁才会调用此private函数。
源码解析
1行: 入参是本次交易(流动性增加/减少)前目前的两个token的余额。出参是是否打开收税开关。
2~3行: 通过判断收税地址是否为零地址来确定开关是否打开。
5~8行: 6行表示上次 feeon 开关打开时记录的初始 kLast, 作为收税的起点。7行表示经过n次交易后最新的恒定product平方根, 其和LP token是对应的。注意,恒定成绩是 两个token余额的乘积,但它并非一直不变,流动性增加和减少时,k值也会相应的增加和减少,每次交易后,因为收取0.3%手续费的缘故,k值也会增加,不变是指一笔交易中,交易后扣除收付费后的乘积和交易前的乘积的不变。
9行:如果期间发生交易,该条件才会满足,才会触发收税。
10~12行:收税的计算公式。假设应该收取 费用x, 及新增 x个 LP token并打给收税地址。那么就有了这个公式: , 稍微计算一下就可以转成该三行的代码。其中K2代表当前的乘积,K1代表Klast, T代表总的 LP token目前总发行量。用大白话讲,就是k值平方根的新增比例(产出比例)的1/6应该和 此次我应收取费用的比例(投入比例)是一样的。
13行:铸造并打款给收税地址。