imtoken钱包官网登录|uniswap交易手续费
imtoken钱包官网登录|uniswap交易手续费
Uniswap v3 详解(四):交易手续费 - 简书
wap v3 详解(四):交易手续费 - 简书登录注册写文章首页下载APP会员IT技术Uniswap v3 详解(四):交易手续费YANG_ad29关注赞赏支持Uniswap v3 详解(四):交易手续费本文copy自https://liaoph.com/uniswap-v3-4/以普通用户的视角来看,对比 Uniswap v2,Uniswap v3 在手续费方面做了如下改动:
添加流动性时,手续费可以有 3个级别供选择:0.05%, 0.3% 和 1%,未来可以通过治理加入更多可选的手续费率
Uniswap v2 中手续费会在收取后自动复投称为 LP 的一部分,即每次手续费都自动变成流动性加入池子中,而 Uniswap v3 中收取的手续费不会自动复投(主要是为了方便合约的计算),需要手动取出手续费
不同手续费级别,在添加流动性时,价格可选值的最小粒度也不一样(这个是因为 tick spacing 的影响),一般来说,手续费越低,价格可选值越精细,因此官方推荐价格波动小的交易对使用低费率(例如稳定币交易对)
以开发者的视角来看,Uniswap v3 的手续费计算相对会比较复杂, 因为它需要针对每一个 position 来进行单独的计算,为了方便计算,在代码中会将手续费相关的元数据记录在 position 的边界 tick 上(这些 tick 上还存储了 ΔL 等元数据)。
手续费的计算和存储
在之前的文章中说过,一个交易对池的流动性,是由不同的流动性组合而成,每一个流动性的提供者都可以设置独立的价格范围区间,这个被称为 positon. 当我们计算交易的手续费时,我们需要计算如下值:
每一个 position 收取的手续费(token0, token1 需要分别单独计算)
用户如果提取了手续费,需要记录用户已提取的数值
v3 中有以下几个关于手续费的变量:
交易池中手续费的费率值,这里记录的值时以 1000000 为基数的值,例如当手续费为 0.03% 时,费率值为 300
全局状态变量 feeGrowthGlobal0X128 和 feeGrowthGlobal1X128 ,分别表示 token0 和 token1 所累计的手续费总额,使用了 Q128.128 浮点数来记录
对于每个 tick,记录了 feeGrowthOutside0X128 和 feeGrowthOutside1X128,这两个变量记录了发生在此 tick 「外侧」的手续费总额,那么什么「外侧」呢,后文会详细说明
对于每个 position,记录了此 position 内的手续费总额 feeGrowthInside0LastX128 和 feeGrowthInside1LastX128,这个值不需要每次都更新,它只会在 position 发生变动,或者用户提取手续费时更新
需要注意的时,上面这些手续费状态变量都是每一份 LP 所对应的手续费,在计算真正的手续费时,需要使用 LP 数相乘来得出实际手续费数额,又因为 LP 数在不同价格可能时不同的(因为流动性深度不同),所以在计算手续费时只能针对 position 进行计算(同一个 position 内 LP 总量不变)。
计算过程
我们用 fg 表示代币池收取的手续费总额,对于一个 tick,其索引为 i,使用 fo(i) 表示此 tick 「外侧」的手续费总额,使用 fb(i) 表示低于此 tick 价格发生的交易的手续费总额,使用 fa(i) 表示高于此 tick 价格发生的交易的手续费总额。
1637902293(1).png
1637902313(1).png
流动性价格区间中的手续费计算
1637902354(1).png
fo 的更新
我们知道了某一个 tick 的 fo(i) 的值,与当前 tick ic 和 i 之间的位置关系有关(大于或者小于),在发生交易时,当前价格的 ic 是会不断变化的。因此,当 ic 和 i 的位置关系发生了变化时,我们需要更新 fo(i) 的值。
具体来说,当前价格穿过某一个 tick 时,需要更新此 tick 上的 fo(i),更新的方式时将其值修改为另一侧的手续费总和,即:
fo(i):=fg−fo(i)
core 仓库代码分析
手续费计算的代码的计算主要出现在以下行为相关的代码中:
提供流动性时,需要初始化 tick 对应的 fo 值
发生交易时,需要更新 fg
当交易过程中,当前价格穿过某一个 tick 时,需要更新此 tick 上的 fo 值
当流动性发生变动时,更新此 position 中手续费的总和
提供流动性
在添加流动性时,我们会初始化或更新此 position 对应的 lower/upper tick,在 Tick.update 函数中:
function update(
mapping(int24 => Tick.Info) storage self,
int24 tick,
int24 tickCurrent,
int128 liquidityDelta,
uint256 feeGrowthGlobal0X128,
uint256 feeGrowthGlobal1X128,
bool upper,
uint128 maxLiquidity
) internal returns (bool flipped) {
Tick.Info storage info = self[tick];
// 获取此 tick 更新之前的流动性
uint128 liquidityGrossBefore = info.liquidityGross;
uint128 liquidityGrossAfter = LiquidityMath.addDelta(liquidityGrossBefore, liquidityDelta);
...
// 如果 tick 在更新之前的 liquidityGross 为 0,那么表示我们本次为初始化操作
// 这里会初始化 tick 中的 f_o
if (liquidityGrossBefore == 0) {
// by convention, we assume that all growth before a tick was initialized happened _below_ the tick
if (tick <= tickCurrent) {
info.feeGrowthOutside0X128 = feeGrowthGlobal0X128;
info.feeGrowthOutside1X128 = feeGrowthGlobal1X128;
}
}
...
info.liquidityGross = liquidityGrossAfter;
...
}
1637902499(1).png
交易过程中的手续费
[上一篇]文章中讲过整个交易过程时分步进行的,每一步都在一个相同的流动性区间,那么手续费的计算也需要在每一步的交易中计算出这一步的手续费总数。在交易步骤的结构体中有定义:
struct StepComputations {
...
// 当前交易步骤的手续费
uint256 feeAmount;
}
只计算一个值时因为,手续费只会在输入的 token 中收取,而不会在输出的 token 中重复收取。
计算过程在 SwapMath.computeSwapStep 中:
function computeSwapStep(
...
)
internal
pure
returns (
...
uint256 feeAmount
)
{
...
if (exactIn) {
// 在交易之前,先计算当价格移动到交易区间边界时,所需要的手续费
// 即此步骤最多需要的手续费数额
uint256 amountRemainingLessFee = FullMath.mulDiv(uint256(amountRemaining), 1e6 - feePips, 1e6);
...
} else {
...
}
...
// 根据交易是否移动到价格边界来计算手续费的数额
if (exactIn && sqrtRatioNextX96 != sqrtRatioTargetX96) {
// 当没有移动到价格边界时(即余额不足以让价格移动到边界),直接把余额中剩余的资金全部作为手续费
feeAmount = uint256(amountRemaining) - amountIn;
} else {
// 当价格移动到边界时,计算相应的手续费
feeAmount = FullMath.mulDivRoundingUp(amountIn, feePips, 1e6 - feePips);
}
}
1637902593(1).png
// 交易步骤的循环
while (state.amountSpecifiedRemaining != 0 && state.sqrtPriceX96 != sqrtPriceLimitX96) {
// 计算这一步的手续费总额
(state.sqrtPriceX96, step.amountIn, step.amountOut, step.feeAmount) = SwapMath.computeSwapStep(
...
);
// 更新交易的 f_g,这里需要除以流动性 L
if (state.liquidity > 0)
state.feeGrowthGlobalX128 += FullMath.mulDiv(step.feeAmount, FixedPoint128.Q128, state.liquidity);
...
}
...
// 在交易步骤完成后,更新合约的 f_g
if (zeroForOne) {
feeGrowthGlobal0X128 = state.feeGrowthGlobalX128;
if (state.protocolFee > 0) protocolFees.token0 += state.protocolFee;
} else {
feeGrowthGlobal1X128 = state.feeGrowthGlobalX128;
if (state.protocolFee > 0) protocolFees.token1 += state.protocolFee;
}
...
更新时使用此步骤的手续费总额除以此步骤的流动性 L ,以得出每一份流动性所对应的手续费数值。
当 tick 被穿过时
前面说过,当 tick 被穿过时,需要更新这个 tick 对应的 fo,这部分操作也是在 UniswapV3Pool.swap 中:
while (state.amountSpecifiedRemaining != 0 && state.sqrtPriceX96 != sqrtPriceLimitX96) {
...
// 当价格到达当前步骤价格区间的边界时,可能需要穿过下一个 tick
if (state.sqrtPriceX96 == step.sqrtPriceNextX96) {
// 查看下一个 tick 是否初始化
if (step.initialized) {
int128 liquidityNet =
// 在这里需要更新 tick 的 f_o
ticks.cross(
step.tickNext,
(zeroForOne ? state.feeGrowthGlobalX128 : feeGrowthGlobal0X128),
(zeroForOne ? feeGrowthGlobal1X128 : state.feeGrowthGlobalX128)
);
// if we're moving leftward, we interpret liquidityNet as the opposite sign
// safe because liquidityNet cannot be type(int128).min
...
}
...
} else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) {
...
}
...
}
这里通过 ticks.cross 来更新被穿过的 tick:
function cross(
mapping(int24 => Tick.Info) storage self,
int24 tick,
uint256 feeGrowthGlobal0X128,
uint256 feeGrowthGlobal1X128
) internal returns (int128 liquidityNet) {
Tick.Info storage info = self[tick];
info.feeGrowthOutside0X128 = feeGrowthGlobal0X128 - info.feeGrowthOutside0X128;
info.feeGrowthOutside1X128 = feeGrowthGlobal1X128 - info.feeGrowthOutside1X128;
liquidityNet = info.liquidityNet;
}
1637902706(1).png
position 维度
position 由 lower tick 和 upper tick 两个 tick 组成,当 positino 更新时,就可以更新从上次更新以来此 position 中累积的手续费数额。只在 position 的流动性更新时才更新 position 中的手续费可以让交易过程不用更新过多的变量,节省交易所消耗的 gas 费用。在 UniswapV3Pool._updatePosition 中:
function _updatePosition(
address owner,
int24 tickLower,
int24 tickUpper,
int128 liquidityDelta,
int24 tick
) private returns (Position.Info storage position) {
...
// 计算出此 position 中的手续费总额
(uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) =
ticks.getFeeGrowthInside(tickLower, tickUpper, tick, _feeGrowthGlobal0X128, _feeGrowthGlobal1X128);
// 更新 position 中记录的值
position.update(liquidityDelta, feeGrowthInside0X128, feeGrowthInside1X128);
...
}
通过 ilower, iupper, icurrent 和 fg,调用 ticks.getFeeGrowthInside 可以计算出 position 中的手续费总额,代码为:
function getFeeGrowthInside(
mapping(int24 => Tick.Info) storage self,
int24 tickLower,
int24 tickUpper,
int24 tickCurrent,
uint256 feeGrowthGlobal0X128,
uint256 feeGrowthGlobal1X128
) internal view returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) {
Info storage lower = self[tickLower];
Info storage upper = self[tickUpper];
// 计算 f_b(i)
uint256 feeGrowthBelow0X128;
uint256 feeGrowthBelow1X128;
if (tickCurrent >= tickLower) {
feeGrowthBelow0X128 = lower.feeGrowthOutside0X128;
feeGrowthBelow1X128 = lower.feeGrowthOutside1X128;
} else {
feeGrowthBelow0X128 = feeGrowthGlobal0X128 - lower.feeGrowthOutside0X128;
feeGrowthBelow1X128 = feeGrowthGlobal1X128 - lower.feeGrowthOutside1X128;
}
// 计算 f_a(i)
uint256 feeGrowthAbove0X128;
uint256 feeGrowthAbove1X128;
if (tickCurrent < tickUpper) {
feeGrowthAbove0X128 = upper.feeGrowthOutside0X128;
feeGrowthAbove1X128 = upper.feeGrowthOutside1X128;
} else {
feeGrowthAbove0X128 = feeGrowthGlobal0X128 - upper.feeGrowthOutside0X128;
feeGrowthAbove1X128 = feeGrowthGlobal1X128 - upper.feeGrowthOutside1X128;
}
feeGrowthInside0X128 = feeGrowthGlobal0X128 - feeGrowthBelow0X128 - feeGrowthAbove0X128;
feeGrowthInside1X128 = feeGrowthGlobal1X128 - feeGrowthBelow1X128 - feeGrowthAbove1X128;
}
这部分代码使用前面说过的[公式,这里不再详述。
在 Position.update 函数中:
function update(
Info storage self,
int128 liquidityDelta,
uint256 feeGrowthInside0X128,
uint256 feeGrowthInside1X128
) internal
...
// 计算 token0 和 token1 的手续费总数
uint128 tokensOwed0 =
uint128(
FullMath.mulDiv(
feeGrowthInside0X128 - _self.feeGrowthInside0LastX128,
_self.liquidity,
FixedPoint128.Q128
)
);
uint128 tokensOwed1 =
uint128(
FullMath.mulDiv(
feeGrowthInside1X128 - _self.feeGrowthInside1LastX128,
_self.liquidity,
FixedPoint128.Q128
)
);
// update the position
if (liquidityDelta != 0) self.liquidity = liquidityNext;
self.feeGrowthInside0LastX128 = feeGrowthInside0X128;
self.feeGrowthInside1LastX128 = feeGrowthInside1X128;
if (tokensOwed0 > 0 || tokensOwed1 > 0) {
// overflow is acceptable, have to withdraw before you hit type(uint128).max fees
self.tokensOwed0 += tokensOwed0;
self.tokensOwed1 += tokensOwed1;
}
}
这里计算了此 position 自上次更新以来 token0 和 token1 的手续费总数,计算时使用的 feeGrowthInside0X128 的含义时每一份流动性所对应的手续费份额,因此在计算总额时需要使用此值乘以 position 的流动性总数。最后将这些手续费总数更新到 tokensOwed0 和 tokensOwed0 字段中。
手续费的提取
手续费的提取也是以 position 为单位进行提取的。使用 UniswapV3Pool.collect 提取手续费:
function collect(
address recipient,
int24 tickLower,
int24 tickUpper,
uint128 amount0Requested,
uint128 amount1Requested
) external override lock returns (uint128 amount0, uint128 amount1) {
// 获取 position 数据
Position.Info storage position = positions.get(msg.sender, tickLower, tickUpper);
// 根据参数调整需要提取的手续费
amount0 = amount0Requested > position.tokensOwed0 ? position.tokensOwed0 : amount0Requested;
amount1 = amount1Requested > position.tokensOwed1 ? position.tokensOwed1 : amount1Requested;
// 将手续费发送给用户
if (amount0 > 0) {
position.tokensOwed0 -= amount0;
TransferHelper.safeTransfer(token0, recipient, amount0);
}
if (amount1 > 0) {
position.tokensOwed1 -= amount1;
TransferHelper.safeTransfer(token1, recipient, amount1);
}
emit Collect(msg.sender, recipient, tickLower, tickUpper, amount0, amount1);
}
这个函数比较简单,即根据 position 中已经记录的手续费和用户请求的数额,发送指定数额的手续费给用户。
但是这里 posiiton 中的手续费可能并不是最新的(上面说过手续费总数只会在 position 的流动性更新时更新)。因此在提取手续费前,需要主动触发一次手续费的更新,这些操作已经在 uniswap-v3-periphery 仓库中进行了封装。
peirphery 仓库代码分析
流动性对应手续费的更新
NonfungiblePositionManager 中保存了用户提供的流动性,并使用 NFT token 将这个流动性代币化。在更新流动性时,也会更新其累积的手续费数额,例如增加流动性时:
function increaseLiquidity(
uint256 tokenId,
uint128 amount,
uint256 amount0Max,
uint256 amount1Max,
uint256 deadline
) external payable override checkDeadline(deadline) returns (uint256 amount0, uint256 amount1) {
...
(, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, , ) = pool.positions(positionKey);
// 更新 token0 和 tokne1 累积的手续费
position.tokensOwed0 += uint128(
FullMath.mulDiv(
feeGrowthInside0LastX128 - position.feeGrowthInside0LastX128,
position.liquidity,
FixedPoint128.Q128
)
);
position.tokensOwed1 += uint128(
FullMath.mulDiv(
feeGrowthInside1LastX128 - position.feeGrowthInside1LastX128,
position.liquidity,
FixedPoint128.Q128
)
);
position.feeGrowthInside0LastX128 = feeGrowthInside0LastX128;
position.feeGrowthInside1LastX128 = feeGrowthInside1LastX128;
position.liquidity += amount;
}
因此一个流动性对应 NFT token 的手续费也会在流动性变化时更新。
提取手续费
提取手续费使用 NonfungiblePositionManager.collet:
function collect(
uint256 tokenId,
address recipient,
uint128 amount0Max,
uint128 amount1Max
) external payable override isAuthorizedForToken(tokenId) returns (uint256 amount0, uint256 amount1) {
require(amount0Max > 0 || amount1Max > 0);
// 查询 postion 信息
Position storage position = _positions[tokenId];
PoolAddress.PoolKey memory poolKey = _poolIdToPoolKey[position.poolId];
IUniswapV3Pool pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));
(uint128 tokensOwed0, uint128 tokensOwed1) = (position.tokensOwed0, position.tokensOwed1);
// 这里会再次更新一次手续费累计总额
if (position.liquidity > 0) {
// 使用 pool.burn() 来触发手续费的更新
pool.burn(position.tickLower, position.tickUpper, 0);
(, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, , ) =
pool.positions(PositionKey.compute(address(this), position.tickLower, position.tickUpper));
tokensOwed0 += uint128(
FullMath.mulDiv(
feeGrowthInside0LastX128 - position.feeGrowthInside0LastX128,
position.liquidity,
FixedPoint128.Q128
)
);
tokensOwed1 += uint128(
FullMath.mulDiv(
feeGrowthInside1LastX128 - position.feeGrowthInside1LastX128,
position.liquidity,
FixedPoint128.Q128
)
);
position.feeGrowthInside0LastX128 = feeGrowthInside0LastX128;
position.feeGrowthInside1LastX128 = feeGrowthInside1LastX128;
}
// 提取手续费的最大值,不能超过手续费总额
(amount0Max, amount1Max) = (
amount0Max > tokensOwed0 ? tokensOwed0 : amount0Max,
amount1Max > tokensOwed1 ? tokensOwed1 : amount1Max
);
// 调用 pool.collect 将手续费发送给 recipient
(amount0, amount1) = pool.collect(recipient, position.tickLower, position.tickUpper, amount0Max, amount1Max);
// sometimes there will be a few less wei than expected due to rounding down in core, but we just subtract the full amount expected
// instead of the actual amount so we can burn the token
(position.tokensOwed0, position.tokensOwed1) = (tokensOwed0 - amount0Max, tokensOwed1 - amount1Max);
}
这个函数就是先用 pool.burn 函数来触发 pool 中 position 内手续费总额的更新,使其更新为当前的最新值。调用时传入参数的 Liquidity 为 0,表示只是用来触发手续费总额的更新,并没有进行流动性的更新。更新完成后,再调用 pool.collect 提取手续费。
至此手续费相关的管理就全部介绍完了。Uniswap v3 还记录了一个 position 中发生交易的总时长,这个值可以用来计算一个 position 处于活跃状态的总时间数,用于 position 仓位调整参考,这部分计算因为和费率计算类似,内容本文不再赘述,感兴趣的读者可以自行研究。
最后编辑于 :2021.12.30 16:23:47©著作权归作者所有,转载或内容合作请联系作者人面猴序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...沈念sama阅读 147,998评论 1赞 315死咒序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...沈念sama阅读 63,184评论 1赞 263救了他两次的神仙让他今天三更去死文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...开封第一讲书人阅读 98,595评论 0赞 217道士缉凶录:失踪的卖姜人 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...开封第一讲书人阅读 41,982评论 0赞 188港岛之恋(遗憾婚礼)正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...茶点故事阅读 49,919评论 1赞 266恶毒庶女顶嫁案:这布局不是一般人想出来的文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...开封第一讲书人阅读 39,299评论 1赞 183城市分裂传说那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...沈念sama阅读 30,845评论 2赞 282双鸳鸯连环套:你想象不到人心有多黑文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...开封第一讲书人阅读 29,607评论 0赞 175万荣杀人案实录序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...沈念sama阅读 33,040评论 0赞 222护林员之死正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...茶点故事阅读 29,690评论 2赞 225白月光启示录正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...茶点故事阅读 31,047评论 1赞 236活死人序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...沈念sama阅读 27,485评论 2赞 219日本核电站爆炸内幕正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...茶点故事阅读 31,958评论 3赞 215男人毒药:我在死后第九天来索命文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...开封第一讲书人阅读 25,747评论 0赞 9一桩弑父案,背后竟有这般阴谋文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...开封第一讲书人阅读 26,253评论 0赞 175情欲美人皮我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...沈念sama阅读 34,074评论 2赞 239代替公主和亲正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...茶点故事阅读 34,222评论 2赞 241推荐阅读更多精彩内容Uniswap v3 详解(二):创建交易对/提供流动性本文copy自 https://liaoph.com/uniswap-v3-2/[https://liaoph.c...YANG_ad29阅读 4,861评论 0赞 1Uniswap v3 详解(一):设计原理uniswap v3 copy 自 https://liaoph.com/[https://liaoph.com/...YANG_ad29阅读 4,694评论 0赞 1Uniswap v3 详解(三):交易过程本文从copy自https://liaoph.com/uniswap-v3-3/[https://liaoph.c...YANG_ad29阅读 5,162评论 0赞 0基于本体的Chocoswap启动 交易手续费全部回馈给用户基于本体Ontology生态的首个跨链去中心化交易所Chocoswap于北京时间1月9日13时(PST时间1月8日...孤芳自赏币自来阅读 262评论 0赞 0Uniswap V3 要点Uniswap V3 形式上是用极坐标代替直角坐标,用一系列不连续的反比例函数曲线段代替了原来暂时固定的单条曲线,...朱立_SSE阅读 436评论 0赞 0评论0赞赞1赞赞赏更
交易费率 | Uniswap V3 Book 中文版
| Uniswap V3 Book 中文版Uniswap V3 Book 中文版Milestone 0. 简介交易市场简介恒定函数做市商(CFMM)Uniswap V3开发环境Milestone 1. 第一笔交易简介计算流动性提供流动性第一笔交易管理合约部署合约用户界面Milestone 2. 第二笔交易简介输出金额计算Solidity中的数学运算Tick Bitmap Index通用mint通用swap报价合约用户界面Milestone 3. 跨tick交易简介不同价格区间跨tick交易滑点保护流动性计算关于定点数的拓展闪电贷用户界面Milestone 4. 多池子交易简介工厂合约交易路径多池子交易用户界面Tick 舍入Milestone 5. 费率和价格预言机简介交易费率闪电贷费率协议费率价格预言机用户界面Milestone 6: NFT positions简介ERC721 概述NFT 管理员合约NFT 渲染器补充资料中英名词对照
交易费率
交易费率费率如何收集计算 Position 累积费用累积交易费用添加需要的状态变量收集费用在 tick 中更新费用追踪器更新全局费用追踪器位置管理中的费用tick 中费用追踪器的初始化更新 position 费用和 token 数量移除流动性燃烧流动性
\[ \]交易费率
#正如我在简介中所说,交易费率是 Uniswap 的一个核心机制。LP 需要从提供流动性中获得收益,否则它们还不如把这笔钱用来做别的。为了激励它们,每一笔交易中交易员都会付出一小笔费用。这些费用将会按提供的流动性占比分配给所有的 LP。为了更好地理解费用收集和分发的机制,我们来看一下它如何工作。费率如何收集
#交易费用仅仅当一个价格区间在使用中的时候才会被收集到这个区间中。因此,我们需要跟踪穿过价格区间边界的时间。我们希望在下列的时间开始对一个价格区间的费率收集:当价格上升,tick 穿过价格区间的下界;当价格下降,tick 穿过价格区间的上界;而在下列的时刻一个价格区间被停用:当价格上升,tick 穿过价格区间的上界;当价格下降,tick 穿过价格区间的下界;除了知道何时一个区间会被激活/停用以外,我们还希望能够跟踪每个价格区间累积了多少费用。为了让费用计算更简单,Uniswap V3 跟踪一个单位的流动性产生的总费用。之后,价格区间的费用通过总费用计算出来:用总费用减去价格区间之外累计的费用。而在一个价格区间之外累积的费用是当一个 tick 被穿过时追踪的(当交易移动价格时,tick 被穿过;费用在交易中累计)。用这种方法,我们不需要去在每一笔交易中更新每一个位置累计的费用——这会节省大量的 gas,让与池子的交互更加便宜。让我们在进行下一步之前再来回顾一下:用户交易 token 的时候支付费用。输入 token 中的一小部分将会被减去,并累积到池子的余额中。每个池子都有 feeGrowthGlobal0X128 和 feeGrowthGlobal1X128 两个状态变量,来跟踪每单位的流动性累计的总费用(也即,总的费用除以池子流动性)。注意到,此时实际的位置信息并没有更新,以便于节省 gas。tick 跟踪在它之外累积的费用。当添加一个新的位置并激活一个 tick 的时候(添加流动性到一个之前是空着的 tick),这个 tick 记录在它之外累计的费用(惯例来说,我们假设之前所有积累的费用都 低于这个 tick)。每当一个 tick 被激活时,在这个 tick 之外积累的费用就会更新为,在这个 tick 之外积累的总费用减去上一次被穿过时这个 tick 记录的费用。tick 知道了在他之外累积了多少费用,就可以让我们计算出在一个 position 内部累积了多少费用(position 就是两个 tick 之间的区间)。知道了一个 position 内部累积了多少费用,我们就能够计算 LP 能够分成到多少费用。如果一个 position 没有参与到交易中,它的累计费率会是 0,在这个区间提供流动性的 LP 将不会获得任何利润。现在,我们来看一下如何计算一个 position 累积的费用(第六步)。计算 Position 累积费用
#为了计算一个 position 累计的总费用,我们需要考虑两种情况:当现价在这个区间内或者现价在区间外。在两种情况中,我们都会从总价中减去区间下界和上界之外累积的费用来获得结果。但是根据现价情况的不同,我们对于这些费用的计算方法也不同。当现价在这个区间内,我们减去到目前为止,这些 tick 之外累积的费用:当现价在区间之外,我们需要在减去上下界之外的费用之前先对它们进行更新。我们仅仅在计算中更新它们,而不会覆盖它们,因为这些 tick 还没有被穿过。tick 之外累计的费用更新如下:$$f_{o}(i) = f_{g} - f_{o}(i)$$在 tick 之外收集的费用($f_{o}(i)$)是总费用($f_{g}$)与上一次这个 tick 被穿过时累计的费用之差。约等于我们在 tick 被穿过时重置一下其计数器。计算一个 position 内累积的费用:$$f_{r} = f_{g} - f_{b}(i_{l}) - f_{a}(i_{u})$$我们从所有价格区间累积的总费用中,减去在下界之下累积的费用($f_{b}(i_{l})$)和在上界之上累计的费用($f_{a}(i_{u})$)。也即我们上面图中看到的计算方法。现在,当现价高于区间下界时(即区间被激活时),我们不会更新低于下界的费用累积,仅仅从下界中读取这个数据;对上界也是同理。而在另外两种情况时,我们需要考虑更新费用:当现价低于下界 tick,并考虑低于下界累积的费用时;当现价高于上界 tick,并考虑高于上界累积的费用时。希望上面这些不会让你迷惑。幸运的是,现在我们已经理解了一切,并且可以开始写代码了!累积交易费用
#为了简单起见,我们会逐步在我们的代码中添加费率。我们首先从收取交易费用开始。添加需要的状态变量
#我们需要做的第一件事是在池子中添加费率参数——每个池子都有一个固定且不可变的费率,在部署时配置。在前一章中,我们添加了工厂合约来简化池子的部署。池子部署参数中的一个是 tick 间隔。现在,我们将会把这个参数替换成费率,并且我们会把费率和 tick 间隔绑定:费率越高,tick 间隔越大。这是因为稳定性越高的池子(稳定币池)的费率应该更低。让我们更新工厂合约:// src/UniswapV3Factory.sol
contract UniswapV3Factory is IUniswapV3PoolDeployer {
...
mapping(uint24 => uint24) public fees; // `tickSpacings` replaced by `fees`
constructor() {
fees[500] = 10;
fees[3000] = 60;
}
function createPool(
address tokenX,
address tokenY,
uint24 fee
) public returns (address pool) {
...
parameters = PoolParameters({
factory: address(this),
token0: tokenX,
token1: tokenY,
tickSpacing: fees[fee],
fee: fee
});
...
}
}
费率的单位是基点的百分之一,也即一个费率单位是 0.0001%,500 是 0.05%,3000 是 0.3%。下一步是在池子中累积交易费用。为此我们要添加两个全局费用累积的变量:// src/UniswapV3Pool.sol
contract UniswapV3Pool is IUniswapV3Pool {
...
uint24 public immutable fee;
uint256 public feeGrowthGlobal0X128;
uint256 public feeGrowthGlobal1X128;
}
带 0 的那个跟踪 token0 累积的费用,带 1 的跟踪 token1 累积的费用。收集费用
#现在我们需要更新 SwapMath.computeSwapStep——这是我们计算交易数量的函数,同时也是我们计算和减去交易费用的地方。在这里,我们把所有的 amountRemaining 替换为 amountRemainingLessFee:uint256 amountRemainingLessFee = PRBMath.mulDiv(
amountRemaining,
1e6 - fee,
1e6
);
这样,我们就在输入的 token 中减去了交易费用,并且用这个小一点的结果计算输出数量。这个函数现在也会返回在这一步中累计的交易费用——它的计算方法根据是否达到了区间的上界而有所不同:bool max = sqrtPriceNextX96 == sqrtPriceTargetX96;
if (!max) {
feeAmount = amountRemaining - amountIn;
} else {
feeAmount = Math.mulDivRoundingUp(amountIn, fee, 1e6 - fee);
}
如果没有达到上界,现在的价格区间有足够的流动性来填满交易,因此我们只需要返回填满交易所需数量与实际数量之间的差即可。注意到,这里没有使用 amountRemainingLessFee,因为实际上的费用已经在重新计算 amountIn 的过程中考虑过了(译者注:此处建议参考对应代码片段更清晰)。当目标价格已经达到,我们不能从整个 amountRemaining 中减去费用,因为现在价格区间的流动性不足以完成交易。因此,在这里的费用仅考虑这个价格区间实际满足的交易数量(amountIn)。在 SwapMath.computeSwapStep 返回值后,我们需要更新这步交易累计的费用。注意到仅仅有一个变量来跟踪数值,这是因为当关注一笔交易的时候,我们已经知道了输入 token 是 token0 还是 token1(而不会是两者均有):SwapState memory state = SwapState({
...
feeGrowthGlobalX128: zeroForOne
? feeGrowthGlobal0X128
: feeGrowthGlobal1X128
});
(...) = SwapMath.computeSwapStep(...);
state.feeGrowthGlobalX128 += PRBMath.mulDiv(
step.feeAmount,
FixedPoint128.Q128,
state.liquidity
);
这里我们用费用除以流动性的数量,为了让后面在 LP 之间分配利润更加公平。在 tick 中更新费用追踪器
#接下来,我们需要在 tick 中更新费用追踪器(当交易中穿过一个 tick 时):if (state.sqrtPriceX96 == step.sqrtPriceNextX96) {
int128 liquidityDelta = ticks.cross(
step.nextTick,
(
zeroForOne
? state.feeGrowthGlobalX128
: feeGrowthGlobal0X128
),
(
zeroForOne
? feeGrowthGlobal1X128
: state.feeGrowthGlobalX128
)
);
...
}
由于我们此时还没有更新 feeGrowthGlobal0X128/feeGrowthGlobal1X128 状态变量,我们把 state.feeGrowthGlobalX128 作为其中一个参数传入。cross 函数更新费用追踪器:// src/lib/Tick.sol
function cross(
mapping(int24 => Tick.Info) storage self,
int24 tick,
uint256 feeGrowthGlobal0X128,
uint256 feeGrowthGlobal1X128
) internal returns (int128 liquidityDelta) {
Tick.Info storage info = self[tick];
info.feeGrowthOutside0X128 =
feeGrowthGlobal0X128 -
info.feeGrowthOutside0X128;
info.feeGrowthOutside1X128 =
feeGrowthGlobal1X128 -
info.feeGrowthOutside1X128;
liquidityDelta = info.liquidityNet;
}
我们还没有添加对于 feeGrowthOutside0X128/feeGrowthOutside1X128 变量的初始化——我们会在后面步骤中完成。更新全局费用追踪器
#最后一步,当交易完成时,我们需要更新全局的费用追踪:if (zeroForOne) {
feeGrowthGlobal0X128 = state.feeGrowthGlobalX128;
} else {
feeGrowthGlobal1X128 = state.feeGrowthGlobalX128;
}
同样地,在一笔交易中只有一个变量会更新,因为交易费仅从输入 token 中收取。现在交易部分就完成了!现在我们来看看,当添加流动性时费用会发生什么变化。位置管理中的费用
#当添加或移除流动性的时候(后者我们还没有实现),我们也需要初始化或者更新费用。费用在 tick 中(在 tick 之外累计的数量,feeGrowthOutside)和在 position 中(position内部累积的费用)都需要进行跟踪。在 position 中,我们也需要跟踪和更新收集的费用数量——或者换句话说,我们把每单位流动性的费用转换成 token 数量。因为当 LP 移除流动性的时候,它们需要获得一定数量的交易费用。我们来一步一步完成它。tick 中费用追踪器的初始化
#在 Tick.update 函数中,当一个 tick 被初始化时(添加流动性到一个空的 tick),我们初始化它的费用追踪器。然而,我们仅当 tick 低于现价的时候做这件事,也即当现价在现在价格区间内时:// src/lib/Tick.sol
function update(
mapping(int24 => Tick.Info) storage self,
int24 tick,
int24 currentTick,
int128 liquidityDelta,
uint256 feeGrowthGlobal0X128,
uint256 feeGrowthGlobal1X128,
bool upper
) internal returns (bool flipped) {
...
if (liquidityBefore == 0) {
// by convention, assume that all previous fees were collected below
// the tick
if (tick <= currentTick) {
tickInfo.feeGrowthOutside0X128 = feeGrowthGlobal0X128;
tickInfo.feeGrowthOutside1X128 = feeGrowthGlobal1X128;
}
tickInfo.initialized = true;
}
...
}
如果现价不在价格区间内,费用追踪器将被设置为0,并且会在下一次这个 tick 被穿过时进行更新(参考我们上面写的 cross 函数)。更新 position 费用和 token 数量
#下一步是计算 position 累计的费用和 token 数量。由于一个 position 就是两个 tick 之间的一个区间,我们使用 tick 中的费用追踪器来计算这些值。下面这个函数可能看起来有点复杂,但它实现的正是我们之前看到的价格区间费用计算的公式:// src/lib/Tick.sol
function getFeeGrowthInside(
mapping(int24 => Tick.Info) storage self,
int24 lowerTick_,
int24 upperTick_,
int24 currentTick,
uint256 feeGrowthGlobal0X128,
uint256 feeGrowthGlobal1X128
)
internal
view
returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128)
{
Tick.Info storage lowerTick = self[lowerTick_];
Tick.Info storage upperTick = self[upperTick_];
uint256 feeGrowthBelow0X128;
uint256 feeGrowthBelow1X128;
if (currentTick >= lowerTick_) {
feeGrowthBelow0X128 = lowerTick.feeGrowthOutside0X128;
feeGrowthBelow1X128 = lowerTick.feeGrowthOutside1X128;
} else {
feeGrowthBelow0X128 =
feeGrowthGlobal0X128 -
lowerTick.feeGrowthOutside0X128;
feeGrowthBelow1X128 =
feeGrowthGlobal0X128 -
lowerTick.feeGrowthOutside1X128;
}
uint256 feeGrowthAbove0X128;
uint256 feeGrowthAbove1X128;
if (currentTick < upperTick_) {
feeGrowthAbove0X128 = upperTick.feeGrowthOutside0X128;
feeGrowthAbove1X128 = upperTick.feeGrowthOutside1X128;
} else {
feeGrowthAbove0X128 =
feeGrowthGlobal0X128 -
upperTick.feeGrowthOutside0X128;
feeGrowthAbove1X128 =
feeGrowthGlobal0X128 -
upperTick.feeGrowthOutside1X128;
}
feeGrowthInside0X128 =
feeGrowthGlobal0X128 -
feeGrowthBelow0X128 -
feeGrowthAbove0X128;
feeGrowthInside1X128 =
feeGrowthGlobal1X128 -
feeGrowthBelow1X128 -
feeGrowthAbove1X128;
}
这里我们计算两个 tick 之间累计的费用。首先我们计算低于下界 tick 的费用,然后是高于上界 tick 的费用。在最后,我们把这些费用从全局积累的费用中减去。这正是我们之前看到的公式:$$f_{r} = f_{g} - f_{b}(i_{l}) - f_{a}(i_{u})$$当计算在某个 tick 之上/之下累积的费用时,我们根据当前价格区间是否被激活(现价是否在价格区间内)来进行不同操作。当它处于活跃状态,我们只需要使用当前 tick 的费用追踪器的值;当它处于停用状态,我们需要使用 tick 更新后的费用——你可以在上面代码里两个 else 分支的计算中看到。得到 position 内累积的费用后,我们可以更新 position 内的费用和数量追踪器了:// src/lib/Position.sol
function update(
Info storage self,
int128 liquidityDelta,
uint256 feeGrowthInside0X128,
uint256 feeGrowthInside1X128
) internal {
uint128 tokensOwed0 = uint128(
PRBMath.mulDiv(
feeGrowthInside0X128 - self.feeGrowthInside0LastX128,
self.liquidity,
FixedPoint128.Q128
)
);
uint128 tokensOwed1 = uint128(
PRBMath.mulDiv(
feeGrowthInside1X128 - self.feeGrowthInside1LastX128,
self.liquidity,
FixedPoint128.Q128
)
);
self.liquidity = LiquidityMath.addLiquidity(
self.liquidity,
liquidityDelta
);
self.feeGrowthInside0LastX128 = feeGrowthInside0X128;
self.feeGrowthInside1LastX128 = feeGrowthInside1X128;
if (tokensOwed0 > 0 || tokensOwed1 > 0) {
self.tokensOwed0 += tokensOwed0;
self.tokensOwed1 += tokensOwed1;
}
}
当计算应得的 token 时,我们把费用乘以区间的流动性——与我们在交易时所作的相反。在最后,我们更新费用追踪器,并把 token 数量加到之前的数量上。现在,每当一个 position 发生变动(添加或移除流动性),我们计算这个区间收集的费用并且更新 position 信息:// src/UniswapV3Pool.sol
function mint(...) {
...
bool flippedLower = ticks.update(params.lowerTick, ...);
bool flippedUpper = ticks.update(params.upperTick, ...);
...
(uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = ticks
.getFeeGrowthInside(
params.lowerTick,
params.upperTick,
slot0_.tick,
feeGrowthGlobal0X128_,
feeGrowthGlobal1X128_
);
position.update(
params.liquidityDelta,
feeGrowthInside0X128,
feeGrowthInside1X128
);
...
}
移除流动性
#我们现在可以来添加我们唯一一个没有实现的核心功能了——移除流动性。与 mint 相对应,我们把这个函数叫做 burn。这个函数允许 LP 移除一个 position 中部分或者全部的流动性。除此之外,它也会计算 LP 应该得到的利润收入。然而,实际的 token 转移会在另一个函数中实现——collect。燃烧流动性
#燃烧流动性与铸造相反。我们现在的设计和实现使得这个任务非常简单——燃烧流动性仅仅是符号为负的铸造。它就等同于添加负数的流动性。为了实现 burn,我们需要重构代码,把 position 管理相关的代码(更新 tick 和 position,以及 token 数量的计算)移动到 _modifyPosition 函数中,这个函数会被 mint 和 burn 使用。function burn(
int24 lowerTick,
int24 upperTick,
uint128 amount
) public returns (uint256 amount0, uint256 amount1) {
(
Position.Info storage position,
int256 amount0Int,
int256 amount1Int
) = _modifyPosition(
ModifyPositionParams({
owner: msg.sender,
lowerTick: lowerTick,
upperTick: upperTick,
liquidityDelta: -(int128(amount))
})
);
amount0 = uint256(-amount0Int);
amount1 = uint256(-amount1Int);
if (amount0 > 0 || amount1 > 0) {
(position.tokensOwed0, position.tokensOwed1) = (
position.tokensOwed0 + uint128(amount0),
position.tokensOwed1 + uint128(amount1)
);
}
emit Burn(msg.sender, lowerTick, upperTick, amount, amount0, amount1);
}
在 burn 函数中,我们首先更新 position,并从中移除一定数量的流动性。接下来,我们更新这个 position 应得的 token 数量——它包含提供流动性时转入的 token 数量以及费用收入。我们也可以把它看做把 position 流动性转换到 token的过程——这些 token 将不会再被用于流动性,并且可以通过调用 collect 函数来赎回:function collect(
address recipient,
int24 lowerTick,
int24 upperTick,
uint128 amount0Requested,
uint128 amount1Requested
) public returns (uint128 amount0, uint128 amount1) {
Position.Info memory position = positions.get(
msg.sender,
lowerTick,
upperTick
);
amount0 = amount0Requested > position.tokensOwed0
? position.tokensOwed0
: amount0Requested;
amount1 = amount1Requested > position.tokensOwed1
? position.tokensOwed1
: amount1Requested;
if (amount0 > 0) {
position.tokensOwed0 -= amount0;
IERC20(token0).transfer(recipient, amount0);
}
if (amount1 > 0) {
position.tokensOwed1 -= amount1;
IERC20(token1).transfer(recipient, amount1);
}
emit Collect(
msg.sender,
recipient,
lowerTick,
upperTick,
amount0,
amount1
);
}
这个函数仅仅是从池子中转出 token,并确保只能转出有效的数量(不能够转出超过燃烧+小费收入的数量)。这种方式也可以在不燃烧流动性的情况下取出费用收入:燃烧流动性数量设置为 0,然后调用 collect。在燃烧过程中,position 会被更新,应得的 token 数量也会更新。就是这样!我们的池子实现现在已经完成了!交易费率费率如何收集计算 Position 累积费用累积交易费用添加需要的状态变量收集费用在 tick 中更新费用追踪器更新全局费用追踪器位置管理中的费用tick 中费用追踪器的初始化更新 position 费用和 token 数量移除流动性燃烧
Uniswap V3新特性解析——为了挣取更多手续费,LP需要承担更大的无常损失吗 - 知乎
Uniswap V3新特性解析——为了挣取更多手续费,LP需要承担更大的无常损失吗 - 知乎首发于加密世界切换模式写文章登录/注册Uniswap V3新特性解析——为了挣取更多手续费,LP需要承担更大的无常损失吗加密喵There is no free lunch. Higher risk / higher return. The more concentrated your liquidity, the higher your fees, the more IL you experience. ——Hayden Adams世上没有什么免费的午餐。风险越高,收益越高。你提供的流动性越集中,你获得的手续费收入就越高,同时也将承担更多的无常损失。——Uniswap创始人,Hayden Adams我们知道,Uniswap V3最主要的改进,就是为LP增加了流动性聚合功能,帮助LP更好的集中资金以获得更多的手续费回报。然而更高的收益也往往蕴含着风险,正如Uniswap创始人在Twitter上表示的,资金的集中会带来更多的无常损失。那么,在新版本的Uniswap中,LP应该如何调整自己的做市策略,才能获得更好的收益呢?(为便于理解,以下论述过程中,都将以ETH-USDC交易对为例进行分析) (1) 无常损失是源于套利交易吗我们需要先回顾一下无常损失问题。对于这个话题,一个最常见的解释便是:“LP遭受的无常损失,被在市场间进行套利的套利者赚走了。”然而,事实真的是这样吗?我们来做一个简单的假设。如果从现在起,除Uniswap以外所有的交易市场全部关闭,剩余的交易者全部集中到唯一的市场Uniswap中进行交易,那么套利者自然也会一同消失。而由于在这个过程中,Uniswap本身的代码没有发生任何变化,LP遵循的价格曲线与无常损失,也一定都会与之前表现的完全一致。所以,无常损失只能是系统内生的,与外部套利者没有直接的联系。再换一个角度思考这个问题。大家知道,我们中文中所谓的无常损失,英文的原词其实是impermanent loss,如果将其直译成中文的话,就是“非永久损失”。也就是说,由价格上涨产生的无常损失,在价格下跌后就会消失。如果认为无常损失是被套利者拿走了,那么在价格下跌的时候,难道是套利者又把赚走的钱还回来了。(2) 重新理解无常损失我们知道,在做市过程中,做市商要被动的与整个市场不停地进行方向相反的交易。而这种被动交易造成的结果,就是当ETH价格持续上涨,LP就会被动地在上涨前以更低的价格不断出售ETH,而在ETH价格持续下跌的时候又会过早的高价买回。翻译成更容易理解的话就是:牛市的时候卖早卖便宜了(少赚等于亏);熊市的时候抄底抄早了(越买越跌)。由于这些交易都是LP在AMM算法下被动执行的,所以主观上我们便会认为,这是由于LP参与做市而产生的附带损失。而随着V3版本的发布,LP将可以根据自己的选择,在原价格曲线中截取其中一部分进行做市。其结果就是,相比原先在完整曲线上的交易速度,LP在价格上涨的过程中,将以更快的速度,分批卖出自己持有的ETH。显然,LP手中更多的ETH以更早更便宜的价格,在价格上涨前被自动卖掉了。于是V3版中采取流动性聚合方式进行做市的LP,自然也承担了更大的无常损失。(3) 如何成为一个合格的做市商为了更好的制定自己的交易策略,一个合格的做市商,首先需要明确自己面对哪些具体的风险。这里我们需要把话题稍微拉远一点,先从传统市场的做市商谈起。传统做市商为了履行做市职责赚取利润,需要在市场上以较低的价格收购某一种证券,并以更高的价格出售证券。在这个过程中,做市商将不可避免的持有一段时间的证券头寸。但是请注意,做市商的最终目的是以法币为本位币进行盈利,所以其在做市过程中持有的证券头寸,只是为了随时向需要买入证券的交易者提供流动性,不得已而保持的存货。如果在做市过程中,存货的价格上升或下跌,都会对做市商的最终盈利产生较大的影响。而这部分风险,也就是存货风险,并不是做市商希望承担的。因此,传统做市商的风险管理策略就是,在保证市场充足流动性的基础上(也就是交易者可以随时从做市商处买到想要的证券),尽量减少自己持有存货的数量,尽可能的降低存货风险。相比于传统做市商,自动做市商改进了报价的生成方式。在新的自动做市系统中,报价不再是由做市商主动报出,而是由一个固定在智能合约中的数学公式自动生成。由于报价工作不再由人工判断生成,于是这种做市方式便被改称为自动做市商(Automated Market Maker,以下简称AMM)。鉴于在新的AMM架构中,做市商失去了原有的报价职能,只保留了向市场提供流动性的功能,人们便也不再称其为做市商,而是改称其为流动性提供者(liquidity provider,以下简称LP)。两者的关系可以简化为以下等式:自动做市商(AMM)=AMM自动报价算法+流动性提供者(LP)虽然报价职能的免除,使得成为AMM交易所LP的门槛大大降低,但是LP所面对的主要风险,依然如传统MM一样,是自己不希望持有的那一种资产的存货风险,而不是什么无常损失。如果你预期ETH的价格还会上涨,那么你LP头寸中所有以USDC形式存在的资金,都将失去享受ETH上涨带来收益的机会,这才是所有LP更应该关注的问题。所以,LP的主要策略,依然是如何在做市过程中,尽量减少存货风险。正如Hayden所说的:“对于LP来说,存货风险造成的损失,经常远大于无常损失。”(4) 在V3版本中如何调整做市策略由于LP的主要风险依然是存货风险,所以LP的主要做市策略,不应仅仅是无常损失最小化,而是存货风险最小化。这里根据LP对未来价格走势的不同预期,对不同情况下的最优做市策略进行一下分析。1. 稳定币或锚定币交易对这种交易对最大的特点,就是两个币种的相对价格变动程度非常小,所以LP不会明显偏好其中某一个币种,也就基本消除了存货风险和无常损失的影响。于是对于LP最好的策略,便是尽量高效的赚取手续费,也就是尽可能的在1:1的价格处更多地集中流动性。比如在DAI-USDT的交易池中,设置在0.99-1.01的范围内提供流动性。此外,如果你预期ETH的价格将在未来一个月内保持稳定,在2000美元价格处持续横盘震荡。那么,在这个预期的时间段中,也可以暂时以稳定币交易对的思路进行做市策略的安排。例如,在1950-2050美元的范围内进行做市,赚取手续费,并在月底前提前撤回流动性。2. 稳定币与波动币交易对还是以ETH-USDC交易对为例。由于波动币如ETH价格波动幅度较大,所以LP的主要策略,依然是尽量减少自己的存货风险。假设ETH现价为2000美元,如果LP预期ETH未来价格将上涨到2500美元,那么其基本思路应该是,在尽可能保留ETH头寸的同时,赚取一些手续费收入。以下我们分别讨论几个可能的方案。方案一:LP在2000USDC的现货价格两侧(如1900-2100USDC)提供流动性,则LP必须要在做市前处置一部分ETH变为USDC,这个行为与自己看涨ETH的预期不符,产生了存货风险,且ETH会随着价格上涨,全部低价出售变为USDC,LP将会承担极大的无常损失,所以此策略不符合我们的目标。方案二:在高于现货价格处,如2100-2200USDC的范围内提供流动性。由于LP的做市范围高于现价,那么这部分流动性,都会以ETH的形式提供,这个过程不需要出售ETH,符合LP对ETH价格上涨的预期,没有产生存货风险。做市后若ETH价格继续上涨,那么LP持有的ETH头寸都将在2100-2200USDC的价格区间内,逐渐出售换为USDC。在这个过程中,LP开始过早的持有了USDC,开始承担存货风险。同时由于以低于自己的预期价格2500美元以下过早的出售了ETH头寸,会产生较大的无常损失。所以这个策略也不是最好的选择。方案三:在预期的价格高点附近提供流动性,如2490-2500USDC。如果ETH的价格真的如LP预期中上涨超过2500USDC,那么这部分流动性都将从ETH出售变现为USDC,由于出售的价格基本符合LP的价格预期,所以没有产生太大的无常损失。同时,LP可以在出售完成后,可以选择撤回流动性止盈,于是整个过程更类似于一个传统交易所的止盈订单,LP基本避免了存货风险与无常损失的发生。但问题是,LP在此过程中由于过早的撤出了流动性,因此不会赚取太多的手续费,与直接持有现货并在预期的价格下出售没有什么区别,做市的意义显得很低。(5) 结论与建议在投资者预期价格走势为单边行情的前提下,不论在哪个价格范围内提供流动性,都很难在避免存货风险的前提下,赚取较多的手续费。所以在市场波动较大,价格走势预期比较不明确的情况下,成为Uniswap V3版本的LP不是一个比较理智的选择。那么在新版本上线后,有没有可能出现没人做市的情况呢。笔者推断大概率不会。因为不同投资者的预期有差别,总会有人持有未来价格将保持横盘的判断,而在自己认可的价格范围内进行做市。同时,V3版本增加了手续费费率的调整机制,对于风险较大的交易对,市场会选择更高的费率,来弥补LP承担的风险。最后再总结一下本文的主要观点:1. 在做任何决定前,首先想清楚自己的真正需求和将要面对的风险,不要有事没事轻易地去做什么LP;2. 在新的V3版本中,提供流动性成为了一个需要更高专业知识与技能的工作,已经不再适合普通小白进行无脑梭哈了;3. 成为稳定币交易对的LP,基本上还是可以无脑赚钱的。但是要小心别轻易给未经时间验证的稳定币做市,一旦归零,依然可以血本无归;编辑于 2021-04-12 11:53区块链(Blockchain)赞同 132 条评论分享喜欢收藏申请转载文章被以下专栏收录加
去中心化交易所:Uniswap v2白皮书中文版 - 知乎
去中心化交易所:Uniswap v2白皮书中文版 - 知乎切换模式写文章登录/注册去中心化交易所:Uniswap v2白皮书中文版Yeefea原文:Uniswap v2 Core作者:Hayden Adams - hayden@uniswap.orgNoah Zinsmeister - noah@uniswap.orgDan Robinson - dan@paradigm.xyz2020年3月Uniswap v2 核心摘要这篇技术白皮书解释了Uniswap v2核心合约背后的设计决策。内容覆盖了合约的新特性,包括任意ERC20代币的交易对,强化的价格预言机制(price oracle),允许交易者先接收资产并使用,随后在转账中支付的快速互换(flash swaps)功能,在未来可以开启的协议手续费(protocol fee)为了减少受攻击面,重新设计了合约的架构。本白皮书描述了Uniswap v2核心合约的运行机制,包括储存流动性提供者资金的交易对合约,和用于实例化交易对合约的工厂合约。1 介绍Uniswap v1是一个以太坊区块链上的智能合约系统,基于常数乘积公式实现了自动流动性协议。每个Uniswap v1交易对在资金池里储存两种资产,并位这两种资产提供流动性,维持这两种资产的乘积不减少。交易者支付30bp(译者注:0.3%)的交易手续费给流动性提供者。合约是不能升级的。Uniswap v2基于同样的公式实现,添加了几个特性。最重要的一个是支持ERC20代币/ERC20代币交易对,而不像v1只支持ERC20代币/ETH交易对。除此以外,它也强化了价格预言,在每个区块开始处累积两个资产的相对价格。这允许其他以太坊合约计算两个资产在任意时间区间上的TWAP价格。最后,它启用了快速互换(flash swaps)功能,用户可以自由地接收资产并把他们用在链上的其他地方,只要在转账的最后支付(或返还)即可。虽然合约通常来说不可升级,但是有一个私钥能够更新一个变量,打开链上5bp的手续费,这个变量一开始是关闭的,可以在未来打开,打开之后流动性提供者在每笔交易上赚取25bp,而不是30bp。Uniswap v2修复了一些v1中的小问题,也在实现中重新设计了架构,减少了Uniswap的受攻击面,通过把逻辑最小化放在核心合约(core contract)中,这个核心合约维持了流动性提供者的资金,从而使系统变得更容易升级。这篇论文描述了核心合约(core contract)的运行机制,以及用来实例化核心合约的工厂合约(factory contract)。实际上使用Uniswap v2需要通过一个“路由”合约(router contract),计算交易/存款数额并转移资金到交易对合约(pair contract)。译者注:合约代码:https://github.com/Uniswap/uniswap-v2-coreUniswap v1 白皮书:https://hackmd.io/@HaydenAdams/HJ9jLsfTz#%F0%9F%A6%84-Uniswap-Whitepaper2 新特性2.1 ERC20交易对Uniswap v1使用ETH作为过渡货币(bridge currency),每个交易对都包含ETH。这使得路由更简单(ABC和XYZ之间的每笔交易都通过ETH/ABC交易对和ETH/XYZ交易对进行),并且减少了流动性的分散。但是,这个规则给流动性提供者增加了可观的成本。所有流动资金提供者都有ETH的敞口,并且由于其他资产相对于ETH的价格变化而遭受无常损失(impermanent loss)。当两个资产ABC和XYZ相关时(例如,如果它们都是锚定美元的稳定币),则在Uniswap交易对ABC/XYZ上的流动性提供者遭受的无常损失会比ABC/ETH或XYZ/ETH交易对少。使用ETH作为强制性过渡货币也会给交易者带来成本。交易者必须支付的费用是直接购买ABC/XYZ交易对的费用的两倍,因此他们遭受两次滑点。 Uniswap v2允许流动性提供商为任意两个ERC20创建对合约。任意ERC20之间的交易对数量的激增可能会使寻找交易特定货币对的最佳路径变得更加困难,但是路由可以在更高的层面上处理(在链下处理或通过链上路由器或聚合器)。2.2 价格预言(Price oracle)Uniswap提供的t时刻的边际价格(marginal price,不包括手续费)可以用资产a的储备除以资产b的储备来计算。p_t=\frac{r^{a}_{t}}{r^{b}_{t}}\tag{1} 如果这个价格偏离(超出手续费足够的数额),套利者会和Uniswap进行交易使价格回归正常,所以Uniswap提供的价格趋向于追踪资产在相关市场的价格。这意味着它可以被用作一个近似的价格预言。但是用Uniswap v1作为链上价格预言是不安全的,因为它非常容易被操纵。假设一个其他的合约用当前的ETH-DAI的价格交割某个衍生品,操纵价格的攻击者会从ETH-DAI交易对买入ETH,在衍生品上触发结算(引起失真的结算价),然后再把ETH卖给交易对,用真实价格反向交易。这甚至可以用一个原子的转账来完成,或者通过一个控制区块内交易(transaction)顺序的矿工。Uniswap v2改进了预言的功能,通过测算和记录每个区块第一笔交易之前的价格(也就是前一个区块最后的价格)。这个价格比一个区块内的价格更难被操纵。如果攻击者提交了一笔交易(transaction)尝试在区块末尾处操纵价格,其他的套利者可以提交另一个交易(transaction)立即进行反向交易。某个矿工(或有足够gas填满整个区块的攻击者)可以操纵区块末尾处的价格,除非他们可以挖出下一个区块,否则他们他们没有特殊的的套利优势。具体来说,Uniswap v2追踪每个和合约交互的区块开始处的价格的累加和,来累加价格。每个价格用距离上一个更新价格的区块的时间进行加权,根据区块时间戳。这意思是累加器的值在任意时间(更新后)的值等于合约历史上每秒的现货价格的和。a_t = \sum_{i=1}^{t}p_i \tag{2} 要计算从时间 t1到t2的时间加权平均价(译者注:TWAP价格),一个外部调用者可以检查t1和t2时间的累加器的值,将后值减去前值,再除以期间经过的秒数。(注意,合约本身并不记录历史累加值,调用者必须在时间段开始处调用合约来读取和储存这个值。)p_{t_1,t_2} = \frac{\sum\nolimits_{i=t_1}^{t2}p_i}{t_2-t_1}=\frac{\sum\nolimits_{i=1}^{t_2}p_i-\sum\nolimits_{i=1}^{t_1}p_i}{t_2-t_1}=\frac{a_{t_2}-a_{t_1}}{t_2-t_1} \tag{3} 预言的用户可以选择这个区间的起始和结束时间。选择更长的区间可以让攻击者操纵价格的成本更高,虽然这会导致价格变化滞后。一个复杂之处:我们应该用资产B来计算资产A的价格还是用资产A来计算资产B的价格?虽然用B计算的A的现货价格总是用A计算的B的现货价格的倒数,但是在某一时间段内用B计算的A的均价不等于用A计算的B的均价的倒数。举个例子,如果USD/ETH价格在区块1中是100,在区块2中是300,USD/ETH的均价是200 USD/ETH,但是ETH/USD的均价是1/150 ETH/USD(译者注:他们的均价不是倒数关系)。因为合约无法知道用户想要用哪个资产作为账户单位,所以Uniswap v2会同时追踪两个价格。另一个复杂之处:有没有可能某个人发送资产给交易对合约,用来改变它的余额和边际价格,但又不和它交互,因此不会触发价格更新。如果合约简单的检查它自己的余额然后更新预言,攻击者可以在某一个区块中第一次调用合约之前向合约发送资产,从而操纵价格。如果上一次交易的区块是X秒以前,合约会在累加之前错误地把新价格乘以X,即使没有用户用那个价格进行过交易。为了防止这个问题,核心合约在每次交互后缓存它的资金储备,用缓存的资金储备更新价格预言而不用当前资金储备。除了保护价格预言被操纵,这个改动也启用3.2节中描述的合约重新架构。2.2.1 精度Solidity没有一等的非整型数的数据结构的支持,Uniswap v2用简单的二进制定点数格式编码和控制价格。具体来说,某一时间的价格存储为UQ112.112格式,意思是在小数点的任意一边都有112位精度,无符号。这些数字的范围是 [0,2^{112}-1] ,精度是 \frac{1}{2^{112}} 。 选择UQ112.112格式是由于实用的原因,因为这些数可以被存在uint224中,在256位中剩余的32位空余。储备资金各自存在uint112中,剩余32位存储空间。这些空闲空间被用于之前描述的累加过程。具体来说,储备资金和时间戳存储在至少有一个交易的最近的区块中,mod 232(译者注:取余数)之后可以存进32位空间。另外,虽然任意时间的价格(UQ112.112数字)确保可以储存进224位中,但某段时间的累加值确保能存下。存储A/B和B/A累加价格空间尾部附加的32位用来存连续累加溢出的位。这样设计意味着价格预言只在每一个区块的第一次交易中增加了3次SSTORE操作(目前花费15000gas)。主要的缺点是32位不足以储存时间戳并确保不溢出。事实上32位Unix时间戳的溢出日期是2106年7月2日。为了确保系统在这个日期后以及每 2^{32}-1 秒的间隔能够继续运行,预言简单要求每个间隔至少检查一次价格(大约136年一次)。这是由于累加的核心函数(mod取余运算)是溢出安全的,意思是预言用溢出算法计算差值,跨越溢出区间的交易可以被合理计算。2.3 快速互换(Flash Swaps)Uniswap v1中,用户用XYZ买ABC需要发送XYZ到合约,然后才能收到ABC。如果用户需要ABC为了获取他们支付的XYZ,这种方式不方便的。举个例子,用户可能在其他合约中用ABC买XYZ,为了对冲Uniswap上的价格,或者他们可能在Maker或Compound上卖出抵押品平仓然后返还给Uniswap。Uniswap v2添加了一个新的特性,允许用户在支付前接收和使用资产,只要他们在同一个原子的转账中完成支付。swap函数调用一个可选的用户指定的回调合约,在这之间转出用户请求的代币并且强制确保不变。一旦回调完成,合约检查新余额并且确保满足不变(在经过支付手续费调整后)。如果合约没有足够的资金,它会回滚整个交易。用户也可以用同样的代币返还给Uniswap资金池而不完成互换。这高效地让任何人从Uniswap资金池中快速借取任何资产(Uniswap收取同样的千分之三的交易手续费)。2.4 协议手续费(Protocol fee)Uniswap v2包括0.05%协议手续费,可以打开或关闭,如果打开,手续费会被发送给工厂合约中指定的feeTo地址。初始时,feeTo没有被设定,不收手续费。一个预先指定的地址feeToSetter可以在Uniswap v2工厂合约上调用setFeeTo函数,设置feeTo地址。feeToSetter也可以自己调用setFeeToSetter修改feeToSetter地址。如果feeTo地址被设置,协议会收取5pb的手续费,从流动性提供者的30bp手续费中抽取1/6。交易者将在所有交易上支付0.3%手续费,83.3%的手续费给流动性提供者,16.6手续费给feeTo地址。总共收集的手续费可以用自从上次手续费收集以来(译者注:k是常数乘积,可以看v1白皮书)的增长来计算(也就是 )。以下公式给出了t1和t2之间的累加手续费占t2时间资金池中流动性的百分比:f_{1,2} = 1 - \frac{\sqrt{k_1}}{\sqrt{k_2}} \tag{4} 如果fee在时间t1前启用,feeTo地址应该获得1/6的t1到t2时间段内的累加手续费。因此,我们要铸造新的流动性代币给feeTo地址 \phi \cdot f_{1,2} ,其中 \phi = \frac{1}{6} 。我们要选择一个sm满足以下关系,其中s1是t1时刻的流通份额(outstanding shares)总量:\frac{s_m}{s_m+s_1}=\phi \cdot f_{1,2} \tag{5} 经过变换,将替换为后,解得s_m=\frac{\sqrt{k_2}-\sqrt{k_1}}{(\frac{1}{\phi}-1)\cdot\sqrt{k_2}+\sqrt{k_1}} \cdot s_1 \tag{6} 设,得到以下公式s_m=\frac{\sqrt{k_2}-\sqrt{k_1}}{5\cdot\sqrt{k_2}+\sqrt{k_1}} \cdot s_1 \tag{7} 假设初始存款人存了100DAI和1ETH在交易对中,收到10份额。一段时间后(如果没有其他存款人参与)他们把钱转出,这时交易对有96DAI和1.5ETH,用上面得公式可以得出:s_m=\frac{\sqrt{1.5 \cdot 96}-\sqrt{1 \cdot 100}}{5\cdot\sqrt{1.5 \cdot 96}+\sqrt{1 \cdot 100}} \cdot 10 \approx 0.0286 \tag{8} 2.5 资金池份额的元交易(Meta transactions for pool shares)Uniswap v2交易对铸造得资金池份额原生支持元转账。这意思是用户可以用签名授权一个他们的资金池份额的转账,而不用从他们的地址进行链上转账。任何人都可以调用permit函数来以用户的名义发送签名,支付gas手续费并在同一个转账中执行其他操作。3 其他修改3.1 SolidityUniswap v1是用Vyper实现的,一种类似于Python的智能合约预言。Uniswap v2是用更广泛使用的Solidity实现的,因为它在开发的时候需要一些Vyper中不可用的功能(比如翻译非标准ERC20代币的返回值,通过内联汇编访问新的字节码chanid)。3.2 合约重新架构Uniswap v2在设计时优先考虑的一个方面是最小化受攻击表面积和核心交易对合约的复杂度,交易对合约储存了流动性提供者的资产。这个合约中的任何bug都可能是灾难性的,因为数百万美元的流动性可能会被窃取或冻结。在评估核心合约的安全性时,最重要的问题时它是否保护流动性提供者以防他们的资产被窃取或冻结。除了基本的允许资产在资金池中互换的功能,任何支持或保护交易者的特性,都可以在路由合约中处理。事实上,甚至一部分的互换功能也可以被抽出放到路由合约中。之前提到过,Uniswap v2储存有每种资产最近一次记录的余额(为了防止预言机制被操纵)。新的架构利用了这一点来进一步简化Uniswap v1合约。Uniswap v2中,卖方在调用互换函数之前发送资产到核心合约。然后合约通过比较上次记录的余额和最新余额来计算它收到了多少资产。这意味着核心合约对交易者转账的方式是不可知的。除了transferFrom以外,也可能是元交易(meta transaction),或未来任何其他的授权ERC20代币转账的机制。3.2.1 手续费调整Uniswap v1通过转入合约的代币数量,在保持常数乘积不变之前收取交易手续费。合约强制确保了以下公式:(x_{1} - 0.003 \cdot x_{in}) \cdot y_1 >= x_0 \cdot y_0 \tag{9} 使用flash swaps时,Uniswap v2引入了xin和yin可以同时为非零的可能性(当用户想要返还同样的资产,而不是互换时)。为了处理这种情况,同时正确地收取手续费,合约强制确保:( x_1 - 0.003 \cdot x_{in}) \cdot (y_1 - 0.003 \cdot y_{in}) >= x_0 \cdot y_0 \tag{10} 为了简化链上计算,两边同时乘以1000000,得到:(1000 \cdot x_1 - 3 \cdot x_{in}) \cdot (1000 \cdot y_1 - 3 \cdot y_{in}) >= 1000000 \cdot x_0 \cdot y_0 \tag{11} 3.2.2 sync()和skim()函数为了防止特殊实现用来修改交易对合约余额的代币,并且更优雅地处理总发行量超过的代币,Uniswap v2有两个救援函数:sync()和skim()。sync()作用是在代币异步地减少交易对的余额时的恢复机制。这种情况下,交易会收到次优的汇率,如果没有流动性提供者作出反应,交易对会卡住。sync()的作用是设置合约的储备金为合约当前的余额,提供一种稍微优雅一点的恢复机制。skim()作用是在发送到代币的数量溢出了uint112大小的储备金存储空间时的恢复机制,否则交易会失败。skim()函数允许用户将提出交易对当前余额和的差值大于0时,将差值提出到调用者的地址。3.3 处理非标准和非常规代币ERC20标准要求transfer()函数和transferFrom()函数返回布尔值表示调用的成功或失败。一些代币对这两个函数的实现没有返回值,比如泰达币(USDT)和币安币(BNB)。Uniswap v1将这种不标准的函数返回值转换成false,表示转账不成功,并且回滚交易,导致转账失败。Uniswap v2用不同的方式处理非标准的代币实现。具体来说,如果一次transfer()调用没有返回值,Uniswap v2把它转换为成功而非失败。这个改动不应该影响任何遵从ERC20协议的代币(因为那些代币中transfer()总是有返回值)。Uniswap v1此外假设调用transfer()和transferFrom()不能触发Uniswap交易对合约的重入调用。某些ERC20代币违反了这个假设,包括支持ERC777协议的"hooks"的代币。为了完全支持这些代币,Uniswap v2包含了一个“锁”,直接防止重入所有公共的修改状态的函数。这也保护防止了在快速互换(flash swaps)中从用户定义的回调函数重入,如2.3节所描述的那样。3.4 初始化流动性代币供给当新的流动性提供者向现有的Uniswap交易对中存代币时,计算铸造的流动性代币(译者注:流动性代币需要看Uniswap v1白皮书)数量基于现有的代币数量:s_{minted}=\frac{x_{deposited}}{x_{starting}} \cdot s_{starting} \tag{12} 如果是第一个存款人呢?在 x_{starting} 为0的情况下,这个公式不能用。Uniswap v1设初始份额供给等于存入地ETH数量(以Wei计)。这有一定的合理价值,因为如果初始流动性是在合理价格存入的,那么1流动性份额(和ETH一样是18位小数精度代币)大约值2ETH。但是这意味着流动性资金池份额的价值依赖于初始存入的比例,这完全可能是任意值,尤其是因为没有任何比例可以反应真实价格的保证。另外,Uniswap v2支持任意交易对,有许多交易对根本不包含ETH。相反,Uniswap v2初始铸造份额等于存入代币数量的几何平均值:s_{minted}=\sqrt{x_{deposited}\cdot y_{deposited}} \tag{13} 这个公式确保了流动性资金池份额的价值在任意时间和在本质上和初始存入的比例无关。举个例子,假设当前1 ABC的价格是100XYZ。如果初始存款是2 ABC和200 XYZ(比例1:100),存款人会获得份额。这些份额现在应该任然值2 ABC和200 XYZ,加上累加手续费。如果初始存款是2 ABC和800 XYZ(1:400比例),存款人会收到资金池份额。以上公式确保了流动性资金池不会少于资金池中储备金额的几何平均值。但是,流动性资金池份额的价值随时间增长是可能的,通过累加交易手续费或者向流动性资金池“捐款”。理论上,这会导致一种极端情况,最小的流动性份额数量(1e-18份额)过于值钱,以至于无法位小流动性提供者提供任何流动性。为了减轻这种情况,Uniswap v2销毁第一次铸造的1e-15资金池份额,发送到全零地址而不是铸造者。这对任何代币交易对都是微不足道的。但是这显著地提高了上述攻击地成本。为了提高流动性资金池份额价值到100美元,攻击者需要捐献100000美元到资金池总,这会被作为流动性永久锁定。3.5 包装ETH以太坊原生资产ETH的转账接口和ERC20交互用的标准接口不同。结果,以太坊上许多其他的协议不支持ETH,而是使用了一种标准的“包装的ETH”代币,WETH。Uniswap v1是一个例外。因为每个Uniswap v1交易对包含了ETH作为其中一种资产,所以它可以直接处理ETH,而且更高效地使用gas。因为Uniswap v2支持任意ERC20交易对,它现在不再支持无包装的ETH。如果添加这个特性需要两倍的核心代码,并且产生ETH和WETH流动性分散的风险。原生ETH需要包装后才能在Uniswap v2上交易。3.6 确定交易对地址和Uniswap v1一样,Uniswap v2交易对也是通过单一的工厂合约进行实例化的。在Uniswap v1中,交易对合约用CREATE运算码进行创建,这意味着合约地址依赖于交易对创建的顺序。Uniswap v2使用以太坊新的CREATE2运算码来创建确定地址的交易对合约,这意味着可以在链下计算某个交易对的地址,不用查看以太坊区块链的状态。3.7 最大代币余额为了高效地实现预言机制,Uniswap v2只支持最高储备余额 2^{112}-1 。这个数字足以支持总发行量超过一千万亿的18位小数精度的代币。如果储备余额超过了,任何swap函数调用都会失败(由于_update()函数中的检查逻辑)。要从这个状态中恢复,任何用户都可以调用skim()函数从流动性池中删除超出的资产。引用[1] Hayden Adams. 2018. url: https://hackmd.io/@477aQ9OrQTCbVR3fq1Qzxg/HJ9jLsfTz?type=view.[2] Guillermo Angeris et al. An analysis of Uniswap markets. 2019. arXiv: 1911.03380[q-fin.TR].[3] samczsun. Taking undercollateralized loans for fun and for profit. Sept. 2019. url:https://samczsun.com/taking-undercollateralized-loans-for-fun-and-for-profit/.[4] Fabian Vogelsteller and Vitalik Buterin. Nov. 2015. url: https://eips.ethereum.org/EIPS/eip-20.[5] Jordi Baylina Jacques Dafflon and Thomas Shababi. EIP 777: ERC777 Token Standard.Nov. 2017. url: https://eips.ethereum.org/EIPS/eip-777.[6] Radar. WTF is WETH? url: https://weth.io/.[7] Uniswap.info. Wrapped Ether (WETH). url: https://uniswap.info/token/0xc02aaa39b223fe8d0a0e5c4f27e[8] Vitalik Buterin. EIP 10144 声明这篇论文的目的仅作为一般信息。不构成买卖任何投资产品的投资建议或推荐或请求,也不应该被用来评估任何投资决策的业绩,不应该被用于会计、法律或税务建议或投资推荐。本文反映了作者当前的观点,不代表Paradigm和其附属机构,也不一定反映Paradigm、其附属机构以及隶属于Paradigm的个人的观点。本文反映的观点在没有另行更新的情况下可能发生变化。翻译不易,别忘了点赞收藏加关注哦^_^编辑于 2020-10-11 13:26区块链(Blockchain)区块链技术赞同 582 条评论分享喜欢收藏申请
一文看懂Uniswap和Sushiswap - 知乎
一文看懂Uniswap和Sushiswap - 知乎首发于链习生切换模式写文章登录/注册一文看懂Uniswap和Sushiswap蒋梦初交易所历来是区块链领域的兵家必争之地,而去中心化交易所(DEX)则是本次DeFi热潮的主要赛道之一。从势如破竹的去中心化交易所Uniswap,到近几天名声大噪的赛场新星Sushiswap,一场“swap party”变得越发热闹。今天我们来讲讲这两个DEX,看看它们的异同。本文主要内容包括以下6点:l Uniswap和Sushiswap概况;l 这两家DEX的自动做市商(AMM)原理;l Uniswap的激励机制;l Sushiswap的激励机制;l Sushiswap的早期引流方法;l 这二者的风险。Uniswap和Sushiswap概况Uniswap是一家去中心化交易所(DEX),用来进行代币兑换。Uniswap是一个运行在以太坊区块链上的流动性协议,也就是一组部署到以太坊网络的合约,所有的交易都在链上进行。它不仅跟传统的加密货币交易所不同,也跟普通的去中心化代币交易所不同。它和上述交易所最大的不同就在于,它是基于兑换池,而不是订单簿的去中心化交易协议。在这里没有限价的买单卖单,用户与兑换池按照实时的市价进行交易,见下图。所谓的兑换池,指的是一个资金池,用户把一定量的token充入资金池,就可以兑换出同等价格的另一种token。在兑换过程中,交易所收取0.3%的手续费。用户在Uniswap中交易的价格则由这个资金池中的代币比例和算法来决定。这个算法是自动做市商(AMM),后文会详细讲。订单簿兑换池Uniswap在2019年就已经上线,现在它已经是头号DEX了。 Sushiswap也是一家去中心化交易所(DEX),用来进行代币兑换。目前Sushiswap尚未完全启动,在它完全启动后,它实现的功能与Uniswap相同。Sushi是日语寿司的意思,所以有人把这个项目叫寿司。寿司店(sushiswap)菜单Sushiswap协议是今年8月底才从Uniswap分叉而来,它基本延续Uniswap的核心设计,没有构建全新的模式,同样也是采用兑换池+自动做市商(AMM)的模式。另外,Sushiswap的代币池和前端页面设计与Uniswap也基本相同。自动做市商原理上文说过,Uniswap和Sushiswap都是采用基于兑换池的交易协议,依靠自动做市商模式来实现兑换,现在详细讲讲自动做市商(AMM)的原理。Uniswap并不使用订单簿模式来决定代币的价格,相反,代币的价格(汇率)会在用户交易的过程中连续且自动地根据供需量和恒定乘积公式计算得出。恒定乘积公式就是:X*Y=K。其中X和Y分别代表交易池中两种代币的可用数量。配合恒定乘积公式,一个交易对(也即一个流动性兑换池)中的一种代币的价格,根据池中的供给量和交易者的需求量得出,价格会在根据该公式画出的一条曲线上变动。X*Y=K,或者说Y=K/X,就是我们初中学过的反比例函数。当K不变时,X增大,Y必然减小,反之亦然。在DEX里,用户向兑换池中充入token X,X的数量增多了,Y的数量必然减小,而这减少的Y的数量就被用户取出,完成兑换。举例:假设流动性兑换池中有X token1000个,Y token100个,也就是10个X换1个Y。一名用户向兑换池中充入10个X,根据恒定乘积公式计算Y≈99,Y末-Y初=-1,这减少的1个Y就由这个用户拿走,实现了10个X兑换1个Y。AMM原理示例S在实际的Uniswap兑换过程中,还存在滑点的现象。滑点是指用户最终实现兑换的汇率偏离了真实的汇率。比如在上面的例子中,如果用户充500个X,他只能换出33.3个Y,相当于15个X才能换一个Y,用户就要承受损失。当兑换金额相对于兑换池资金量过大,或者说对于一定的兑换金额,兑换池资金太少时,就会出现滑点。但当兑换池中的代币数量充足时,滑点的数额就会减少,而且资金越多,滑点越小。滑点的大小和常说的交易深度大小相反,滑点越小,交易深度越大,用户越能够按照稳定的价格完成交易。同一时刻,ETH兑换LINK,兑换金额太大产生滑点恒定乘积公式的K越大,也就是资金池里的资金越多时,代币交换滑点越小,流动性也就越好。在这里的流动性就是指当用户想完成某一笔兑换时,他就能够在滑点最小的情况下顺利地完成。AMM模式鼓励用户为兑换资金池提供流动性,方式就是用户向流动性资金池中存入等价值的2种代币,比如上面例子里,用户同时存入100个X和10个Y。如果用户存入的2种代币不等值,比如他存入了100个X和100个Y,(此时的市价还是10个X换1个Y)这会造成兑换池里Y的供给相对过剩,X和Y的相对价值就出现了不平衡。套利者灵机一动,向兑换池里存入383.3个X,兑换出51.7个Y,而按照市价他只能换38.33个Y,于是他净赚13.37个Y。兑换池在经过套利者的一番操作后,又恢复了10个X换1个Y的市价,详情见下表。套利使系统重新归于平衡依靠恒定乘积公式的AMM模式需要套利交易来让流动性池中的代币价格与市场价格保持一致。从本质上来说,这些协议依然需要通过外部交易系统来调控流动性兑换池中代币的价格。AMM模式依靠用户为资金池提供流动性完成自动做市,它给用户的激励就是一定比例的兑换手续费。为流动性资金池提供流动性的用户称为流动性提供者(LP Liquidity Provider)。Uniswap的经济激励机制Uniswap给流动性提供者的奖励就是交易所的手续费。流动性提供者可以得到所在流动性池中代币交易的手续费作为奖励,手续费率为0.3%,流动性提供者之间依据存入资金的份额按比例分配。根据上文截图中的数据计算,一天的成交额是40.85亿CNY,一天的手续费就有122万元,经过一段时间的积累,流动性提供者(LP)得到的手续费奖励金额就非常可观了。Uniswap会根据流动性提供者存入资金的数额发给他们一定数量的LP token,我们可以理解为存款奖状或者收据,它是LP获得交易所手续费奖励的凭证。注意:LP token不是Uniswap的项目代币或者说平台币,对于每一种代币交易对有不同的LP token。举个例子具体说明:假设这个交易对是ETH--DAI,目前兑换比例是1ETH--400DAI。我向资金池充了1ETH和400DAI,这个资金池发给我1个LP token,代表我有1份(ETH--DAI)的流动性贡献。这个资金池所产生的手续费进入一个pool,经过一段时间后,pool中共有积累的手续费A个ETH和B个DAI,当我把我的1个LP token交还给Uniswap时,我有权利从pool拿走它按比例对应的手续费。假设此时整个资金池共发出了X个LP token,我的流动性贡献占比就是1/X,我就可以获得A/X个ETH和B/X个DAI,然后再赎回我的1ETH和400DAI。Uniswap通过AMM模式和为流动性提供者奖励手续费的模式,极大地调动了LP的积极性。由于任何人都可以提供流动性并且从中获利,人们有动力为Uniswap提供流动性;交易所获得充足的交易流动性,交易滑点就小,用户体验也好。交易所的运行完全基于市场的需求进行。人工的运维成本大幅降低。在Uniswap中,交易产品的挂牌会是免费的。而且由于不需要再用交易订单的模式,而且流动性也不需要专门的做市商来提供,因此目前证券市场中的做市商的成本就可以取消。降低了上币成本和做市成本,Uniswap对DeFi和整个区块链行业的发展起到了一定的促进作用。为Uniswap提供流动性的用户可以获得经济激励。不过,这种激励存在两个美中不足之处:1)对早期参与流动性提供的用户不够公平。Uniswap能够运转,全凭流动性提供者为它提供了大量的流动性。早期流动性提供者承担了更多的风险,但并没有因此获得更多的收益。Uniswap依靠着早期的LP存入的资金逐步发展,随着它越来越受欢迎,有越来越多的像风投基金、交易所、矿池这样的大资金进入提供流动性。虽然交易手续费累计的很多,但是早期LP的份额被摊薄了,他们没有能够享受到协议成长带来的长期回报。这有点像早期的滴滴司机或者淘宝店主,正是他们让平台实现了发展,然而在平台发展之后他们并没有享受到更多的收益。此外,流动性提供者只有在他们提供流动性时才赚取资金池的交易费。一旦他们撤回资金池中自己的资金,将不再获得相应的收入。2)无常损失得不到补偿。为Uniswap提供流动性可以交易手续费,但也存在无常损失。无偿损失是指流动性提供者按当时的市价存入2种代币,在他要取出这些代币时,它们的兑换价格发生了变化而导致的损失。如果这2种代币中某个代币大幅上涨或下跌都可能导致无常损失。注意,不管涨还是跌,都有可能导致损失。还是以上面表格里的X和Y为例。当10个X换1个Y时,我存入100X和10Y。假设现在行情变化,也就是X和Y的兑换比例变化了:不管现在是10个X换2个Y(Y跌了),还是20个X换1个Y(Y涨了),我如果想赎回我的资金,都必须按照现在的兑换比例,取出价格相等的X和Y,不能破坏资金池中2种代币的比例平衡,不然套利者就又要出动了。这也就是说,我取出来的不是我存入的100X和10Y,而是按照新的市价的兑换比例,比如120X和8Y。而这相比我直接持有100X和10Y不动,是会产生损失的。当然,它本质上也是资产的再平衡,从这个角度看,不算是无常损失。不过,在退出时,如果按照法币计价,可能会出现获得的费用收益不如直接持有代币所得的收益更高的现象。而且这个无常损失,是无偿的损失。Sushiswap的经济激励机制Sushiswap在Uniswap的激励机制基础上做出了一些改变,这是它们二者最大的区别。Sushiswap增加了代币经济激励,也就是将其交易费用的一部分分配给Sushiswap代币SUSHI的持有人。Uniswap没有发行平台币,它每笔交易收0.3%的手续费,再通过LP token的形式把交易费按比例分配给LP(流动性提供者)。Sushiswap发行了平台币SUSHI,它的交易手续费也是0.3%。它将这0.3%的手续费分成2个部分,其中0.25%提供给LP,方法和Uniswap一样;剩下的0.05%将用于回购SUSHI代币,即用这部分钱购买SUSHI代币持有者手里的SUSHI代币。这意味着,SUSHI的价值与Sushiswap平台交易量是挂钩的。在Sushiswap上,交易量越大,SUSHI捕获的价值就越高。SUSHI代币和COMP、LEND、YFI一样,也可以在二级市场交易。此外,为了保证研发和运营的持续,有10%SUSHI代币会用于开发和未来的迭代、审计等。Sushiswap的经济激励机制在Uniswap的基础上做了改进,它保证了早期参与者的长期利益。Sushiswap每个区块将释放100枚SUSHI代币,会均分给所有支持的代币池,LP们还是根据流动性贡献来按比例获得SUSHI。和Uniswap用LP token的形式来分配手续费不同,LP token只有在存入代币对时才发给用户,而SUSHI是每个区块都产生一次,根据用户现在的资金比例分配。这样即使未来有大资金进入Sushiswap,早期参与者的资金份额被摊薄,但是他们之前已经获得的SUSHI代币不会减少,这就相当于是挖到了“头矿”。更何况在最初的100,000个区块,SUSHI产量更高,每个区块释放1,000枚SUSHI。在Sushiswap交易额增长起来后,SUSHI代币的价格也水涨船高,早期参与者凭借着早期相对较高资金份额占比而积累下的SUSHI代币可以享受到Sushiswap长期发展带来的福利。此外,前文提及,Uniswap的LP在赎回了当初存入的代币对之后,就不能再获得交易所的手续费分成了,而Sushiswap的LP即使赎回了资金,也还能够凭借着持有的SUSHI代币获得币价上涨带来的利益。Sushiswap的经济激励机制也并非尽善尽美。SUSHI代币有2个主要用途。第1点是用于投票。投票决定每个区块产生的100个SUSHI在各个代币对兑换池中分配的比例,也就是哪个池子分到的SUSHI奖励多一点;投票决定是不是要新开放某个新代币对兑换池。对于特定的LP来说,这2种投票的目的都是为了让自己获得更多的SUSHI奖励,消耗一部分SUSHI以获得更多的SUSHI。这样会不会造成分配权重大的资金池分配比例越来越大呢,还有待时间的检验。第2点就是上文说的用于兑换那0.05%的手续费。在交易所蒸蒸日上的阶段这当然是好的了,不过如果交易额下降呢。无限通货膨胀的SUSHI和正在下降的手续费分成相互作用,会导致新产生的SUSHI越来越不值钱,对币价下降的预期则会让老持币人竞相抛售。如果他们再从流动性资金池里撤资,交易所流动性不足,引起交易滑点过大,用户体验变差,交易额就会进一步下降。这样的恶性循环会迅速让它承受巨大损失。这样的情形不一定会出现,但是会有这样的风险。虽然在Uniswap中同样存在交易额下降引发流动性下降的恶性循环,不过它没有平台币,也就没有币价下降的第三重刺激。Sushiswap中同样存在无常损失。Sushiswap的大招仅靠改进的经济激励模型,能不能让Sushiswap超越老大哥,坐上DEX头把交椅呢,我们不得而知。不过项目方还想了别的办法,真正的大招还在后头呢。第一步。Sushiswap为Uniswap的流动性提供者提供了赚取SUSHI代币的机会。Uniswap的流动性提供者可以将其LP token质押在Sushiswap,然后在区块高度10750000开始赚取SUSHI代币。目前只收LP token,还不能直接存入代币对。这好比是你在一家大银行Uniswap存了钱,它发给你一个收据,凭此取钱。新银行Sushiswap说,你的收据质押在我这里,1星期以后我给你这张收据发利息,你的钱还在原来的银行,收据你想拿走随时拿走。这样的好事谁不干,于是大家纷纷把Uniswap的LP token质押在Sushiswap。只要LP token第二步。在协议启动大约两周(最初100,000个区块)后,Sushiswap会启动针对Uniswap的流动性池迁移计划。在迁移过程中,首先是这一批用户在Uniswap上进行代币对的赎回,然后将这些代币池迁移,也就是把从Uniswap里取出来的钱存到Sushiswap里。就这样,Sushiswap将获得大量的流动性,它的流动性是从Uniswap那里直接拿来的。近日Uniswap锁仓量(就是资金池的存款量)暴涨,原因就是Sushiswap只收Uniswap的LP token,用户必须先到Uniswap去存钱,换出LP token,才能把它质押到Sushiswap里。复制粘贴你的运行原理,剪切粘贴你的用户。SIGOI!(日语:好厉害)风险最后我们谈一谈这两家DEX的风险。l 技术风险Uniswap在2020年3月19日在以太坊主网上推出了一个新版本,还配合着公开了核心合约的1.0.1版;在发行之前,该版本已经在Rinkeby测试网上测试过一段时间了。这个新版本在以太坊主网上已经使用超过了两个月时间,而且迄今为止,没有出现任何损坏智能合约完整性的问题。Uniswap V2 在上线主网之前经过了充分的测试和审核。对源代码的尽职审核“很有可能”保证了未来不会发现任何重大的问题,不过Uniswap还是发布了一个Bug悬赏,任何人发现了重大漏洞都可以获得奖金。从Sushiswap宣布的信息看,它邀请Trail of Bits、PeckShield、OpenZeppelin、Consensys、Certik、Quantstamp中的其中一家对其合约进行审计。但目前为止还没有完成正式审计。这里是有潜在风险的。即便完成了审计,任何流动性挖矿都存在潜在的智能合约漏洞风险。编写出没有任何错误的代码是非常困难的,而开发人员也不可能设想到所有的潜在风险,尤其是在DeFi发展如此火爆的今天。Uniswap和Sushiswap都存在一定程度的技术风险。审计、测试以及购买智能合约保险都可以降低技术风险。l 经济模型风险许多区块链项目,特别是在DeFi领域,都需要依靠经济激励来激励网络的参与者。有时候经济模型看起来无懈可击,却包含着潜在的风险。对于这两家DEX的LP来说,首先要面对的就是上文所说无常损失风险。而且是为价格波动越大的币种提供流动性,出现无常损失的风险越高,这导致很多用户发现,为DEX提供流动性(也就是流动性挖矿)带来的收益还不如无常损失更多。SUSHI是每个区块产生100个,它与比特币、以太币等不一样。比特币只有2100万枚,而SUSHI是无限通货膨胀的,未来Sushiswap的交易额增长能够跑得过无限通胀呢,现在还没有一个明确的结论。交易额下降会不会引发流动性枯竭,造成恶性循环,这是它们都面临的风险。l 外部风险外部风险指的不是Uniswap和Sushiswap本身存在的风险,而是在它们上线的项目中存在的风险。例如:项目的虚假宣传、项目方大量抛售代币导致币价崩盘等等。只需要建立两个资金池,就可以无上币费、无审查、无成本地“三无上币”,大大降低了项目方发币割韭菜的难度和成本,这简直比2017年还疯狂。结语:以前说币圈一天,人间一年,现在是DeFi圈一天,币圈一年。这两家swap不是“swap party”的谢幕,还会有更多DEX和其他项目粉墨登场。希望各项目能够互相促进,共同为数字金融和区块链行业的发展助力。本文部分观点参考以下文章:有关Uniswap V2的一切:新功能与工作原理。www.8btc.com/article/641872火币观察:SUSHI飙涨行情耀眼,SushiSwap是否存在风险?www.jinse.com/news/blockchain/804917.html从Uniswap看未来的数字资产交易所。www.8btc.com/article/636431全维度深入解析:Uniswap的正面与背面。www.8btc.com/media/636300SushiSwap锁仓超10亿美元,赚钱效应成DeFi繁荣的最大推手。www.jinse.com/news/blockchain/805211.htmlSushiswap:Uniswap的进化?http://blog.csdn.net/lanhubiji/article/details/108289403作者:蒋梦初2020年9月4日编辑于 2020-09-08 21:50区块链(Blockchain)去中心化金融(DeFi)赞同 34020 条评论分享喜欢收藏申请转载文章被以下专栏收录链习生原创,区块链领域,通俗
如何评价uniswap? - 知乎
如何评价uniswap? - 知乎首页知乎知学堂发现等你来答切换模式登录/注册去中心化金融(DeFi)Uniswap如何评价uniswap?如何评价uniswap?显示全部 关注者26被浏览6,616关注问题写回答邀请回答好问题添加评论分享11 个回答默认排序律动BlockBeats关注区块链、数字加密行业,首选媒体—律动BlockBeats 关注采访:Jack,BlockBeats整理:Jaleel、Kaori,BlockBeats编辑:Jack,BlockBeats诞生于 2019 年黑客马拉松 1inch,在 2020 年 DeFi Summer 的助推下,成功地崭露头角。在两位俄罗斯青年 Sergej Kunz 和 Anton Bukov 的引领下,1inch 凭借高效且低成本的交易方式,稳步攀升至 DeFi 聚合器赛道的领头羊位置。根据 DUNE 的数据显示,自上个月来,使用 1inch 的唯一钱包数量已超过 100 万大关,超过了在 2021 年的高峰期。在近期 1INCH 上涨突破 0.5 美元,团队也推出了自己的开发者门户测试版本,该 Web3 SaaS(软件即服务)平台提供了用于开发新产品的 API,包括交易、现货价格、代币信息等。与此对应的,是 DeFi 市场另一只独角兽的接连出击。今年 6 月 13 日,Uniswap 团队宣布推出第四代版本 V4,引入了「Hooks」和「The Singleton」两个新概念。其中,前者 Hooks 尤其受关注。在许多人看来,它似乎成为了 Uniswap 击败所有 DEX 的杀手锏。而在随后的 ETHCC 大会上,Uniswap 又推出了 UniswapX,向流动性聚合器领域发起进攻。在这种接连冲击下,许多 DeFi 创业者都发出了「放弃 DEXs,加入 Hooks」的感叹。上周,在巴黎 ETHCC 大会期间,BlockBeats 对 1inch 联合创始人 Anton Bukov 进行了专访,深度探讨了 1inch 的发展历程、对 DeFi 创新的看法和思考,以及如何应对 Uniswap 的出击等话题。寸拳,1inch 的创新哲学1inch 这个名字蕴含了浓烈的东方哲学,源自李小龙的名招「一寸拳」,这是国际间对中国传统武术中「寸拳」技法的译称——"One Inch Punch"。在深入智能合约前,1inch 联合创始人 Anton Bukov 的初始职业是一名 C++系统工程师,接着因为对苹果开发工具的喜爱而转向 iOS 开发。而当他遇到智能合约后就立刻被强烈吸引了:在编写智能合约时,需要在全新的层面上去思考和编写代码。在 2018 年,通过朋友的介绍,Anton Bukov 和 Sergej Kunz 相遇并瞬间击中,然后在 2019 年的黑客马拉松上,Sergej 和 Anton 一起开发出了 DEX 聚合器解决方案——这就是 1inch 的起源。左为 Sergej Kunz,右为 Anton Bukov「记账创新的重要性被大大低估了」BlockBeats:1inch 在 DeFi 领域做出了独一无二的贡献,我们一直希望能与 1inch 的创始团队有深入的对话,而据我所知,你们还在涉猎一些新项目。Anton Bukov:没错。举例来说,像 =nil; Foundation 这样的组织,不论是在各类大型会议上,还是在会议之外,都在进行着众多的项目,规模大小不一。有些人正在为现有的区块链和 EVM 构建新的功能,还有人则致力于为加密货币领域的 ZK 创造全新的工具。这些项目并非只是在既有的 EVM 和以太坊的框架内进行,而更像是在为加密货币证明的大众市场,或是协议不可知的项目,构建未来的解决方案。对于那些不能带来任何实际价值的项目,我并不感兴趣,我不相信它们能带来任何实际的价值。然而,有一些人在做的事情。例如,当我和他们交谈了 15 到 20 分钟后,我会发现他们正在做一些非常有趣的事情,他们正在解决一个实际的问题。尽管这个问题现在可能还不太大,但是正在变得越来越重要,这让人感到非常鼓舞。BlockBeats:我简单地和 =nil; Foundation 交谈过,了解到他们在Proof Market方面进行的尝试。Anton Bukov:是的,值得一提的是他们所提出的证明市场,这是一个很酷的东西。所有使用零知识证明(ZK)的参与者都需要创建证明,这是一个需要消耗大量资源的过程,包括能源、GPU 和 ASIC。有一些专门的设备能够承担这些工作。就像比特币挖矿需要 ASIC 一样,创建证明也需要 ASIC。这种专用的硬件能够比通用 GPU 更高效、更经济地创建证明。他们试图创建一个市场,你可以在这个市场上发布订单,如果你愿意支付一定的费用,让别人为你生成证明,那么总会有人对你的订单感兴趣并完成它。一旦完成,他们就会生成该证明,并将其提供给能够验证并支付他们的智能合约。我曾经在 Hackathon 上也做过一个类似的项目,创建了一个智能合约,它可以让用户定制个性化的比特币地址,该合约使用了分离密钥生成的方案。因此,没有人知道最终的私钥,甚至那些用 GPU 算力去寻找私钥的人也无法知道。这是不可能的事情。他们只知道私钥的一部分,那部分是将要加到一个他们不知道的数字上的数字。BlockBeats:那是你编写的第一个智能合约吗?Anton Bukov:是的,那是我在 2017 年的一次 Hackathon 上编写的第一个智能合约。由于我在 Solidity 上找不到任何有助于椭圆加密的库,这可能是密码学密度最高且最复杂的智能合约之一。我需要生成私钥公钥,添加公钥,然后我们可以通过公钥的哈希计算地址。我自己实现了这个逻辑,研究了椭圆曲线是如何工作的,根据维基百科和我找到的其他文档编写了代码,然后就奏效了。后来我还找到了一个库,以一种更高效的方式提供了某种中间表示,这对我来说非常有趣。BlockBeats:提到 2017 年,当时许多人都专注于 ICO 之类的投机行为。Anton Bukov:那可能是在 ICOs 之前,或者大概在几个月后,大约在 2017 年中,我们曾开过一些关于发行代币的玩笑。1inch 可能没有其他领域或项目那么专注于代码数量,因为我们坚信确保用户安全的关键在于尽可能简化代码,并在预算允许的范围内进行尽可能多的审计。如果你有一个含有 5000 行代码的协议并且进行了一次审计,与你有一个只有 500 行代码但进行了 10 次审计的协议相比,你的安全性要高出 100 倍。因为审计并不能保证你的协议是安全的。即使经过了形式化验证,也不能保证安全。它只能保证在你了解所有可能的组合的情况下,可能是安全的。但是你可能忽视了其中的某些威胁和潜在用例。过去的经历表明,一些经过形式化验证的项目也会受到黑客攻击。当有人发现他们可以在同一个区块内操纵 LP 代币的价格,他们就会将以太坊和其他资产投入 Uniswap V2 池中,这使得 LP 代币的价格上涨。然而,如果你拥有两个仓位,一个以 LP 代币作为抵押品,另一个以 LP 代币作为债务,在操纵价格的同时,如果一个仓位非常大,另一个仓位却是负的,那么你就可以带着巨额仓位离场,抛弃那个负债的仓位。因此,如果你能操纵资产的价格,甚至在同一区块内将价格抬高,这会给资金市场带来风险。这是人们没有意识到的,而形式化验证也没有解决这个问题。Aave 的一个分支就因为这个问题被黑客攻击。Aave 关闭了这些智能预言机,因为它们对这种攻击毫无防备。这就是形式化验证不能使项目百分之百安全的例子。我们相信,每次审计都会增加你的安全性,代码越少,审计越多,就越安全。当然,作为拥有 15-20 年软件开发经验的工程师,我们也花费大量时间提高效率和 GAS 效率。在智能合约方面,唯一的优化目标就是智能合约代码的大小和 GAS 效率,我们试图在这两个参数之间找到平衡。代码简洁性和功能紧凑性的平衡BlockBeats:其实在很多人的想象中,DeFi 动态聚合器的代码一定非常复杂。Anton Bukov: 我们会在代码的简洁性和紧凑性之间找到一种平衡,并不意味着我们要把所有的东西都只放在一行代码里。我们只做必要的事情,而且要以高效的方式去做。写代码时常会使用数据结构和算法来帮助处理复杂性和 gas 成本,但我们找到了另一种巧妙的方式,提出新的记账算法,这是在算法领域被低估的一个话题,即算法中的记账创新。来自 Paradigm 的一位成员也在 Twitter 上提到了这个话题,他同样认为记账本身是一个被低估的领域,将在 DeFi 中带来很多创新。这个领域就是。例如,在 2020 年,我和我的同事创建了一个农场智能合约。第一个具有农场激励机制的智能合约是我和我的同事为 Synthetics 协议编写开发的,这个协议每周通过脚本发送激励。我们加入他们的 Discord 提出:「你们为 Uniswap V2 的流动性提供了激励,但是那些提供流动性的人拥有 LP 代币,为什么你们不为这些奖励制定一个质押合约呢?」他们都惊讶于我们刚来就提这个建议。我还说,我们可以编写这个合约。于是我们编写了这个合约,并由 Sigma Prime 审核。这个合约可能是以太坊上被复制最多的智能合约之一。你可能记得 DeFi Summer 时有很多「食物代币」,它们主要就是基于这个智能合约。这是一个记账创新的例子,因为在这个智能合约的重要部分就是人们可以加入「农场」,也可以离开「农场」,这个「农场」可能有数千甚至数百万的用户。但当他们加入和离开时,它是如何运作的呢?「农场」在一段时间内平均分配所有的资金,比如每周分配一定数量的代币,每秒、每分钟、每个区块都在分配同样的金额,但是这些资金是按照用户的质押比例分配的。这里只有三个操作:存款、取款和领取奖励。这三个操作都不包含钱包的枚举,这种方法的复杂度被称为常量复杂度。这意味着,无论我们有一千个用户,还是一百万个用户,这三个方法执行所需要的 gas 成本都是完全相同的。BlockBeats:DeFi 的哪一点吸引了你的关注?又是如何想到 DEX 聚合器这个点子的?Anton Bukov: 因为我们看到这个领域仍然存在大量的未被挖掘的潜力。我们在算法和记账上的创新想法非常有创新,尽管我们已经拥有货币市场、AMMs 等,但记账方式这个领域仍被严重低估了。以加密货币市场为例,它的运作方式很有趣。人们将他们的资产存入一个池子中,这个池子会混合所有人的钱,然后你可以借入其他资产。比如说,你将你的以太坊存入,然后借出比特币。你实际上是从那些存入比特币的人那里借钱的,而不是从某个特定的人那里借的,所以这个过程不是点对点的,而是一个池对池的交互。这种模式使得你的债务和抵押品每秒都在增加。但是这是如何运作的呢?比如说,如果一半的 USDC 抵押品被借出,那些借款人每年需要支付 6% 的利息,他们的债务每年增长 6%,但这个数字是每秒都在增加的。那些提供流动性的人,一半的流动性被借出,支付 6% 的利息,但这些流动性提供者获得的年化收益率为 3%,因为这 6% 的一半按照 100% 的存款比例分配,作为 3% 的年化收益率,而且这个数字也是每秒计算的。为什么是每秒计算的呢?因为最初当我想到这个作为一个黑盒子的借贷概念时,我以为当你归还时需要支付额外的费用,比如你借了 100 美元,归还时你需要支付 105 美元,这笔钱会按比例分配给所有人,但如果你只按照目前在池子里的人来分配,那么就有空间给操纵者。有人可能会插队,存入 99% 的流动性,获得这 5 美元的奖励,然后在你之后立即取出。所以你应该把这 5 美元奖励分配给曾经在池子里的所有人,根据他们在一段时间内的持有比例。他们所做的就是让你的债务和抵押品每秒都在增长。所以对于操纵者来说,插队是没有意义的,因为分配已经发生了。当有人偿还债务时,并不意味着他会支付一笔将被分配的款项,这笔钱已经被分配了,他只是在还清自己的债务,这是一个伟大的记账创新。Compound 和 Aave 的实现方式不同,Compound 会通过不断提高 Compound 资产价格与基础资产的价格比来分配奖励。这个价格每秒都会根据一个公式增加。当借贷的比率发生变化时,他们会调整这个比例。Aave 的做法与此相似,但他们保持 1:1 的价格比,所以你的余额会不断增长,这是一种不同的方法,可以相互转换。任何人都可以编写一个代币封装器,让其表现得像一个 Compound 代币。它的余额不会增长,而是价格会增长。而且还可以创建一个反向封装器代币,可以让 Compound 代币封装器表现得像其他代币,与基础资产一对一,余额不断增长。我相信有人可能已经做了这个项目,比如 X token 项目之类的,他们通常会做一些封装器,允许实现类似的功能,比如投票功能、自动投票、委托等。对于为什么我们选择在 DeFi 领域创新,我想说我们并不仅仅关注 DeFi。我们也非常关注 Web3,并寻求在这方面创新。通常,我们会想出一些独特的技术创新和想法,然后尝试理解我们是否可以基于这些创新和想法构建一个有用且成功的产品。我注意到有些项目首先设想一个产品,然后试图实现它。但我认为 1inch 的做法与之相反,我们首先提出创新,然后尝试理解如何利用这种记账方法或这种算法来最好地服务于用户。这也是为什么我们的大部分产品都能在落地时做得很好,并且很难有人能与之竞争。开发者门户,1inch 在憋什么大招?7 月 19 日,1inch Labs 宣布其开发者门户(Developer Portal)测试版的发布,这是一个 Web3 云 SaaS(软件即服务)平台,为开发新产品提供最先进的 API。1inch 开发者门户提供的 SaaS 解决方案包括:可为用户在特定区块链上交换的加密货币数量提供报价的 Swap API ;根据可用的流动性,在支持的网络上提供加密货币的当前现货价格的 Spot Price API ;为加密货币钱包余额和限额提供准确信息的 Balance API ;基于 1inch 限价单协议的 Orderbook API ;提供用户钱包中所有 NFT 信息的 NFT API 等其他诸多功能。据官方说明,1inch 开发者门户经过验证的解决方案,已在 1inch Wallet 和 1inch dApp 中成功测试。已经集成 1inch API 的项目包括 MetaMask、Trust Wallet 和 Ledger。1inch 开发者门户提供 99% 的正常运行时间服务级别协议。1inch API 为用户提供极短的响应时间,延迟是市场上是最低的。同时,1inch Swap API 可访问多个区块链上的众多流动性来源。便捷的界面可以让用户能够访问最新文档、高级请求统计数据,以及有关 1inch 协议的所有重大升级信息。一个团队应该如何看待行业创新?BlockBeats :让我们来谈谈产品。1inch 最新发布的开发者门户和之前提供给开发者的 API 有何不同?Anton Bukov:Web3 领域的许多开发者都曾参加或仍在参加 Hackathon。我认为,在 Hackathon 上,快速交付成果非常关键。这里存在一条帕累托法则,即付出 20% 的努力就可以得到 80% 的结果,这就是在 Hackathon 上需要追寻并实现的目标。然而,为真正的用户交付产品还需要完成剩下的 20%,而这将需要你投入 80% 的精力。这正是我们的新开发者门户(DevPortal)希望解决的问题。我们花费大量时间为自己、我们的钱包和我们的产品构建所有这些服务。然后,我们决定如果我们能让其他开发者访问所有这些高质量的 API,他们将能够更快地推进自己的产品,更快地验证他们的假设是否符合市场需求,无需投入那 80% 的努力就能实现那 20% 的功能。BlockBeats :开发者可以用这些 API 构建哪些类型的应用或实现呢?Anton Bukov:可能性是无穷的,可以是钱包,也可以是 dApps。如果你打算制作一个钱包,那么你投入的 20% 的努力和得到的 80% 的结果可能就是用户界面,可能是一个移动应用或者 Web 应用。然而开发后端获取钱包的所有代币,这些代币的价格,历史变动,历史记录,这些要在链上,是更大的工作。但是如果有人想要运行一个新的钱包并验证人们是否喜欢它,他们就无法在没有后端的情况下实现这一点。而现在,他们可以只使用我们的 API 来进行尝试,对于大多数人来说,这都是免费的。BlockBeats :在整个 1inch 生态系统中,1inch 钱包将扮演什么角色?Anton Bukov:我们坚信我们的使命是改进这个领域,加速奇点的发展。因此,我们认为公司的唯一生存之道就是创新。我们不仅仅想要生存,还想要持续创新,这也是驱使我们前进的动力。当然,我们有时会感到我们在与其他项目竞争,但这是好事,因为这对我们来说是充满挑战的。我们最初是从 Hackathon 起步的,2019 年我们参加了 15-20 场 Hackathon,对于最终用户来说,竞争总是有益的。在区块链的每个领域都存在竞争,钱包之间、聚合器之间都存在竞争,几乎在所有 Web3、区块链、DeFi 技术所提供的市场中都存在竞争。然而,这些竞争的最大赢家通常都是用户,这真的很棒。这个行业还很年轻,十年后可能会有很大变化。但我们现在所做的一切对于构建这个光明的未来都是有益的。我们发布了这些 API,不仅是为了我们自己内部的使用,也是为了让所有人都能使用,我们相信这将推动行业构建更多的应用。我们并不害怕竞争,因为我们认为这个领域有巨大的发展空间,即使我们在钱包市场上只占有 10% 或 15% 的份额,我们也不在乎。我们仍然处理了超过一半的聚合交易,并一直努力提高我们的市场份额。当然,我们会为我们的份额竞争。但总的来说,我们更希望让这些市场发展得更快。我们的目标不是在小市场上竞争,而是要让整个市场更快地发展。拥有更多不同的钱包可能会吸引更多的人加入到 DeFi 中来,我们希望让整个市场比现在发展得更快。在产品创新和市场增长之间的做出平衡BlockBeats:能透露一下 1inch 现在最赚钱的功能或产品是什么吗?Anton Bukov:实际上,我们并没有从 Swap 中获得收入,因为我们现在的资金充足,我们并不急于赚钱。我们认为,现在更重要的是增长。如果我们需要获得更多的资金,有许多方法可以做到。但在 2023 年的现在,我认为我们离停止增长还有很长的路要走,整个行业在未来 3-5 年内可能会增长 10 倍,因此增长更为重要。许多项目把所有的收入和投资都用于增长,而不是赚钱,许多公司也是如此,比如 Uber。有时,这些公司可能因为高杠杆而生存艰难,他们试图花更多的钱,赚更多的钱,投资更多。但问题是,当投资者看到这些钱都去哪里时,他们会发现这些钱都投入到了增长上,通常不仅仅是在 DeFi 领域,还包括了不断增长的市场和新兴市场。因此,市场中最大的公司非常专注于整个市场的增长和自身在市场中的增长。BlockBeats :在 Fusion 之后,你觉得 1inch 的下一个重大更新会是什么?Anton Bukov:我们现在正在探索下一步可能关注的产品,我们已经设计了一些尚未发布的产品。最初,我们有超过 10 个想法,然后进行了一番头脑风暴。我们对这些想法进行了排序,有三个听起来特别好。我们会继续进行这样的过程,直到决定哪一个可能最符合当前市场和形势的需求。所以现在还没有具体的决定。这也是我们从未公开路线图的原因。市场变化非常快,六个月后市场或许会变得完全不同,我们可能会开发出不同的产品。我们也不能完全确定在接下来的六个月中,我们会做什么。如果我们有一个长期的路线图,但我们又改变了想法,那么很多人可能会感到不满,因为他们认为原来的路线图很好,新的路线图不行。我们的目标是始终超越预期,所以我们不发布路线图,总会有人认为他们比你更懂,他们总会有不满。BlockBeats :谈论创造新产品或创新时,必须考虑产品交付的问题,市场正在快速变化,特别是在 DeFi 领域。你们是如何调整产品的开发方向和实际执行的市场适应性呢?Anton Bukov:我们不会花超过半年的时间来开发一个产品或下一个版本的产品。通常,我们需要的时间会少得多,大约两到三个月,可能稍微多一些。有些开发工作可能从 solidity 智能合约开始,然后在审计期间,我们会有前端、后端等工作。通常是两到三个月左右,可能在某些情况下会稍微多一点。如果我们的产品周期是一年,我们就会被市场淘汰。当你发布它时,可能没人会去用,它可能会变得毫无用处。比如 Uniswap 团队,据我了解,他们在交付产品方面平均需要一年左右的时间。他们说这是 Uniswap X,关于 V3 版本,我相信他们在此之前甚至一年多就开始宣传了,但他们一直在研究 AMM 领域,例如 V3 是 AMM 创新,这个市场在过去一到两年中一直相当稳定。但是,当我们在不同方向、不同 DeFi 领域构建时,我们不能接受这种情况。Uniswap 接连出击,1inch 如何应对?此前,Uniswap 创始人在 ETHCC 上宣布,即将推出跨 AMM 、基于荷兰式拍卖的聚合协议:UniswapX。对于这一款即将上线的新产品,社区和市场做出的评价褒贬相半。Paradigm 研究员 Dan Robinson(@danrobinson)在社交媒体上对 UniswapX 的改变给予高度评价:「我认为 UniswapX 改变了去中心化交换、MEV 和互操作性的游戏规则」,且详细列举出了五个原因。但 Curve Finance 官方账号却做出了不同的评价,他们的看法带有一丝别样的韵味:「恕我直言。游戏规则在很久以前就已经改变了:当 1inch 第一次进行高质量聚合时,当 CoWSwap 推出 Solvers 模型时。UniswapX 是不错,但它并不是开创者,甚至也不是第二个玩家。」无疑,Curve Finance 认为 Uniswap 在抄袭。一些社区成员也纷纷发出疑问:「UniswapX = CoWSwap + 1inch?」相关阅读:《褒贬相半,Uniswap 究竟是不是「币圈腾讯」?》粉色阴影BlockBeats:你提到了 Uniswap,他们最近发布了其重要的 V4 版本以及 UniswapX。尽管其他协议早就提出了类似的创新,但 Uniswap 对这些创新的二次采用还是让其他协议黯然失色。我想听听你对这个问题的看法,一个 DEX 团队作为 Uniswap 的对手,现在应该如何在 DeFi 领域发展?Anton Bukov:当我第一次听说 UniswapX 时,我的第一反应是想知道为什么它和 1inch Fusion 看起来如此相似。当我们深入研究了他们的白皮书后,我们发现 1inch Fusion 是他们最重要的参考之一。我认为这是一种肯定,这再次证明我们和其他在市场上做类似事情的参与者正朝着正确的方向前进。这也再次强调了我们总是领先一步。我坚信,我们的解决方案将继续领先于行业。BlockBeats:许多不同的 DeFi 协议进行了很多创新,但市场并没有给予他们足够的关注。但当 Uniswap 实施了类似的创新后,整个市场就突然觉得这就像一场革命一样。Anton Bukov:是的,我认为有些项目已经具有了不公平的优势,这里的不公平优势是指他们有一些审计师,由于品牌效应,这些审计师成为了他们服务的敲门砖。但这种情况正在慢慢得到解决,因为市场在自我调整。人们开始意识到聚合器的存在,当他们看到 DEX 聚合器时,几乎立刻就能理解到 DEX 虽然不错,但 DEX 聚合器总是领先一步。市场上的不平等和不公平几乎无处不在,在自由市场和非严格监管的市场上,这种情况得到了改善。非监管市场的增长速度远快于监管市场,而且它们的不平等状况随着时间的推移也在逐渐改善。BlockBeats:我还想谈谈商业许可证的问题。在 Fusion 发布后,你们宣布了 MIT 许可,这与 Uniswap 采用的 BSL 许可有很大的区别,MIT 许可更加开放。你怎么看 Uniswap 在许可证方面的做法,为什么选择 MIT 许可?Anton Bukov:我们并不特别害怕竞争,我们的大部分智能合约解决方案都是完全开源的。MIT 许可允许任何人使用我们编写的代码做任何事情。我们认为,不是所有的软件工程师,特别是匿名的软件工程师,都会尊重你的许可。我在 Uniswap V3 的商业许可到期之前就已经看到了一些不知名的团队的分叉。商业许可可能会阻止一些公开团队或公平的竞争者进行分叉,但它无法阻止一些随机的公开分叉。我们认为,如果有人受到我们的想法的启发,那是件好事。我们开发了这个产品,即使有人复制或稍作修改,我们仍然是领先的。当我们发布新版本时,我们通常会已经在开发下一个版本,并且每个新版本都比前一个版本更先进。所以我们通常不太担心被复制,我们把这看作是对公众利益的贡献。BlockBeats:在 DEX 领域,Uniswap 正在走向极致,并且正朝着垄断性的方向前进。现在的 DeFi 领域,还有哪些方向对于创业者来说仍有发展空间?Anton Bukov:我认为创新仍然有空间,仍然有东西可以发明。但从技术角度发明出一些重要的东西之前构建项目或产品可能没有什么意义。仅仅对 Uniswap 或其他项目进行细微的改变,这可能行不通。这样根本无法扩大市场份额。但是好的一面是如果你能找到一个很好的设计,XS AMM 就能得到关注,因为如果你的协议相对于其他协议能提供更好的价格,你的协议就会立即被聚合器所采纳。如果它能提供优秀的价格和对 LP 有吸引力的收益,你就可以取得成功。有可能会有某个天才想出一个天才的方法,发布一个协议,吸引几十万左右的流动性。这个新的 AMM 或 DEX 可能会被聚合器所接纳,从而获得其首批交易量,为 LP 带来丰厚的收益。随着更多的 LP 的加入,项目将逐步发展壮大,在市场上占据数万的份额是有可能的。在聚合器出现之前,新建的 DEX 之间会有很多竞争对手。某个 Hackathon 的参赛者可能会想出一个非常好的解决方案,它被投入使用并在市场上获得竞争份额。以前要获得市场的 10% 份额是不可能的,仅凭一个想法和一点流动性是不够的。你必须吸引用户,因为没有人会进行兑换,但现在,你可以自动获得交易量。所以聚合器的市场定位与 Uniswap 目前的业务有所不同。在聚合器发明之后,有很多 DEX 出现了,而以前很多 DEX 因为没有用户而消亡,但是当聚合器出现时,很多 DEX 能够生存下来并取得成功,获得一些份额继续生存。BlockBeats:目前大家对 1inch 的印象主要还是一个 DeFi 聚合器,未来你们如何在 DeFi 市场中定义自己?Anton Bukov: 是的,1inch 的主要业务仍然是聚合器,我们不认为 Uniswap X 的发布会有很大的变化。我们已经在市场上看到了其他的聚合器,过去三年半我们与他们竞争得相当成功。在最初的半年里,我们几乎是市场上唯一的玩家。我相信事情会有所改变,但并不像有些人想象的那么剧烈。我们有一些并非仅仅是聚合器的产品,还将拥有更多不同的产品。次级 DeFi 可能会针对不同的市场进行监管,比如美国和欧洲的次级 DeFi,也应该添加针对中国的次级 DeFi,因为这是一个非常庞大的市场。可能还有其他市场,比如日本,也是一个庞大的经济体,我们可以通过国家或国家联盟的经济规模来看待BlockBeats:你是否担心未来 Uniswap 的流动性过强,进而影响到 1inch 的大规模采集和使用呢?Anton Bukov:他们一直有很多不公平的交易量,所谓不公平是指聚合器按照不同 DEX 提供的价格公平地分配交易量。当一个用户群体在 Uniswap 上交易,却不使用其他 DEX 或聚合器时,他们可能会有一些交易量。如果这些交易量相对于他们的流动性和价格而言过高,那就是我所说的不公平交易量。从我们在一两年前的测量结果来看,这个问题非常严重,但现在正在逐渐好转。这个市场,和其他所有市场一样,正在变得更好。很多人在 Uniswap 上交易,是因为他们在 TikTok 上听说过它,并不知道其他 DEX 或聚合器的存在,但无论如何,他们最终会为此付出代价,因为这个市场实在太疯狂了。如何看待 DeFi 的未来?BlockBeats:有些人表示,他们正将策略转向在 V4 hooks 上构建一些东西,而不是开发新的 DeFi 应用。从你的角度来看,什么是最好的策略?Anton Bukov:你可以通过 V4 hooks 来引入去中心化交易平台的一些创新,可以在现有的去中心化交易平台之上进行创新,增加额外的功能,如预言机或类似的东西。Uniswap 看到他们的协议被分叉了很多次,而这些变化很小,实际上并没有改变 Swap 的逻辑,他们改变的是其他方面。这个带有分叉的 V4 将允许其他开发者在顶部添加自己的功能,收费或不收费,或者其他任何东西,而无需分叉他们的代码,他们仍然能够通过这些池进行交易,只是带有一些 hooks,现在他们不会通过 SushiSwap 或其他任何平台进行交易。Anton 在 ETHCC 会场BlockBeats:但这会缩小市场或者降低人们建立自己的交易平台并利用聚合器获得即时流动性的积极性,从而导致市场上的技术堆栈减少吗?Anton Bukov:讨论的重点并不是减少交易平台的数量,而是减少现有交易平台的分叉。你可以拥有你自己的 Hooks,我们会很高兴收取费用或其他任何东西。但是如果你想在没有任何重要创意的情况下复制 Uniswap,请不要制造分叉,这没有任何意义。我们可能会看到更少的 Uniswap 分叉,但可能会有更多的 Hooks。BlockBeats:很多开发者都放弃了创建 DEX 的计划,转而研究 Hooks。Anton Bukov:他们在某种程度上仍然可以通过 DEX 来实现,但是与 Uniswap 的 V3 和 V4 解决方案相比,竞争确实变得更加困难,我相信 V4 会比 V3 更强大,V3 并没有完全取代 v2,可能是因为 V2 的 GAS 费用要低得多,这就是为什么 v2 仍然具有大量流动性,而 Uniswap 及其路由器仍然支持 v2 和 V3。但很可能 V3 会完全转移到 V4,因为 V4 比 V3 更好,在 V3 中保留流动性没有意义了,不过我相信他们的路由器会支持 V3。我们曾经有过一些关于自有预言机和其他事物的想法,但我们总是在为我们需要维护一个全新的 AMM 及其所有流动性而挣扎。然而我们认为 Uniswap 在改善这个市场方面做出了很好的举措。因此,我们正在探讨我们到底能提供什么,我们可以开发哪些能够大幅改善某些方面的 Hooks,改进预言机,或者提高 LP 的利润。我们正在探索这一切,并且可能会想出一些组合,这些组合可能会成功,并将大量流动性吸引到我们开发的 Hooks 上。BlockBeats:这或许会是聚合器发挥作用的地方,它不一定是 DEX 聚合器,还可以是很多其他东西?Anton Bukov:是的,已经有了收益、DEX、桥接的聚合器。我认为每个市场都是不同的,聚合 DEX 时我们并没有增加用户的风险。我们可以从第一天开始添加很多 DEX,用户不会承担任何新的风险,因为我们的智能合约在处理所有的风险。但当我们谈论到收益聚合时,这会给用户带来新的风险,从本质上讲这不应该像 1inch 那样。我们可以将一切隐藏在一个交易的幕后,但我认为他们仍然应该向用户展示选择性,用户应该决定使用哪个桥接,哪个更快,多得 10 美元还是在 2 分钟而不是 20 分钟内完成一切,你不能替用户做决定。BlockBeats:我记得你去年在 ETH Denver 上也提到了关于 DeFi 的监管问题,但最近关于监管的讨论越来越多,比如与 RWA 等相关的问题。你是否仍然认为 DeFi 可能需要在诸如稳定币之类的问题上寻求自己的解决方案?Anton Bukov:关于监管,我可以说的是,不同的国家和地区对于监管有不同的要求和想法。但问题是如果他们试图通过让协议或用户遵循与非监管 DeFi 不兼容的规则来进行监管,这不会损害 DeFi,这会创造一个 DeFi 的子市场,这是一种子 DeFi。DeFi 允许用户和协议的子集在自我限制和监管方面进行互动,所以他们不能监管 DeFi,只能以某种方式创造一个受监管的子 DeFi。我们可能会看到针对美国、欧洲地区的受监管子市场,我们已经有了一个相当庞大的 DeFi 市场,如果一些国家希望他们的经济与这个新兴行业融合,就需要接受它。监管是有可能的,但它应该非常微弱,不应是阻止接受现有 DeFi 的东西。例如,我们前几个月看到巴黎银行创建了稳定币,人们在推特上嘲笑它。它的代币看起来像是 ERC20,但与 ERC20 完全不兼容,也绝对不会与现有 DeFi 的大部分现有协议一起使用。你可以试着让它运行,但它可能会破坏事物。因为现有协议假定 ERC20 按照标准中的描述工作,如果你的代币运行方式不同,就可能会破坏它。例如,Uniswap V3 根本无法运行,因为它们在追踪存款用于交换或提供流动性时的余额变化时,之前的版本从源头或智能合约转移,会认为转移发生了,余额已经更新,但实际上并没有,所以奇怪的事情可能会发生,他们的代币无法接入现有 DeFi。他们正在创建一种新的市场,我很好奇是否会出现至少一个支持他们解决方案的协议。很可能不会发生这种情况,他们不会成功的。发布于 2023-08-02 18:22赞同 12添加评论分享收藏喜欢收起沈志强公众号「沈志强」作者,欢迎订阅交流。 关注在进行区块链资产交易时,有两大主要的交易途径,它们分别是 dex 交易和 cex 交易,也就是去中心化交易所交易和中心化交易所交易。从行业现状来看,类似于币安和 okx 这样的中心化交易所还是占据着整个加密货币交易的大部分份额,因为在中心化交易所中进行交易相对来说更简单安全一些,但可交易得标的则远远没有去中心化交易所多;而去中心化形式的交易中,Uniswap 则占据着妥妥的头龙地位。写在前面,我接下来写的东西很可能是错的,如果您看到我的错误,欢迎对我的错误提出指正,感谢。同时,我所有关于区块链资产交易的内容都不构成对您的任何投资建议。另外,我之前也写过系列区块链领域相关文章,感兴趣的朋友可点击文章上方「#区块链」标签随时了解。1什么是 Uniswap?在聊 Uniswap v4 之前,我想我们可以稍微回顾一下有关于 Uniswap 本身的一些基础认识。Uniswap Labs:开发 Uniswap 协议以及 Web 界面的公司。Uniswap 协议:一套持久的、不可升级的智能合约,共同创建一个自动做市商,该协议促进以太坊区块链上的 ERC-20 代币的点对点做市和交换。Uniswap 界面:一个 Web 界面,允许与 Uniswap 协议轻松交互。该界面只是与 Uniswap 协议交互的多种方式之一。Uniswap 治理:用于管理 Uniswap 协议的治理系统,由 UNI 代币启用。该部分来源于 Uniswap 官方文档,链接:https://docs.uniswap.org/concepts/overview《什么是 ( https://docs.uniswap.org/concepts/overview《什么是 ) Uniswap?》官方文档中还包含了非常多的其他的基础性的概念介绍,对 Uniswap 感兴趣的朋友,就非常值得去好好看看里面的内容了。那么,接下来我也向大家快速汇报下我对于 Uniswap 的整体理解。应该说,Uniswap 在区块链领域是一个非常大的创新,它的出现无疑促进了整个区块链资产交易活动,现在 Uniswap 已经成为了区块链领域中的一个基础设施了。如要简单理解 Uniswap 的话,我们可以先回想一下传统金融中的股票交易市场。在股票交易中,很多都是通过限价订单簿的形式促成交易的,也就是买卖双方可以对标的物自行定价,然后将该价格挂到交易系统中,只要有人接受该价格,那么这笔交易就会成交。像币安、okx 这样的交易所就相当于股票交易所,它们搭建了一个平台,吸引所有人去交易。有个挺重要的基础是,币安、okx 是最大的流动性提供方,这是它们能够吸引到别人去自己平台交易的原因之一,只是它们是中心化的一个场所。那么,在去中心化环境中,能不能也实现类似的交易呢?Uniswap 团队给出了自己的解决方案,那就是提供一个自动做市机制来替代订单簿。自动做市机制允许所有人提供流动性,这样一来就巧妙解决了一般标的物流动性提供的问题,只要标的运作良好,就不用担心流动性问题。这也促成了链上大量的可交易的标的出现,给整个行业注入了不少活力。2Uniswap 协议核心内容Uniswap 于 2018 年 11 月 2 日由西门子 ( https://en.wikipedia.org/wiki/Siemens )前机械工程师 Hayden Adams 创建,截止目前,Uniswap 协议已经历经了 3 次升级,分别是 Uniswap v1、Uniswap v2 和 Uniswap v3。现阶段,链上交易普遍使用得是 Uniswap v2 和 Uniswap v3,Uniswap v1 已经没有人在使用了。由于 “年代久远”,我也没有仔细了解 Uniswap v1 的情况;所以,接下来我们主要聊得就是 Uniswap v2 和 Uniswap v3。不论是 Uniswap v1、Uniswap v2 还是 Uniswap v3,自动做市机制的实现都依赖于这样一个算法实现:x * y = k。这个算法的意义就在于每一个 Uniswap v1 交易对池子都包含两个代货币,在提供流动性的过程中保证两种代币余额的乘积无法减少。也就是说,在目标代币的价格不断变化的过程中,流动性提供者的池子中的两个代币的数量会自动发生变化,但始终保持二者乘积不变。比如:有人提供了 ETH/DAI 交易对的流动性,当 DAI 价格上涨时「这里可以理解成有其他用户用他的 ETH 想要在这个池子中购买 DAI」,Uniswap 就会自动将池子中的 DAI 卖出一部分「也就是卖给那个目标用户」换成 ETH「其实是将那个目标用户的 ETH 给到了这个头寸的流动性提供者」,那么效果就是当 DAI 价格上涨时,流动性提供者的 ETH 数量会逐渐增加,DAI 的数量会逐渐减少。反过来,当 DAI 价格下跌时,流动性提供者的 ETH 数量会逐渐减少,DAI 的数量会逐渐增加。而在这个过程中,有人为目标标的的交易提供了流动性,实际上是为所有想要交易目标标的的人提供了流动性;那么哪些想要交易目标标的的人就需要为这些流动性提供者支付一些手续费,这些就是 Uniswap 为 LP(流动性提供者)所做出的激励。在交易手续费上,Uniswap v1 设置的手续费比例是固定的 0.3%,Uniswap 协议本身在交易过程中不收取任何费用;Uniswap v2 由于支持在工厂合约中修改一个合约,这使得 Uniswap 能够针对每笔交易收取 0.005% 的手续费,而 LP 则只能收到 0.025 的手续费,只是该开关默认是关闭的,Uniswap 可在未来某个时间打开该开关;Uniswap v3 则在手续费收取上更加灵活,因为交易手续费将不再限定在 0.3%,而是允许 LP 在设置交易对或者说提供流行性时自行设置手续费率,目前 Uniswap 可支持用户自行设置的手续费率有 0.05%,0.3%和 1%,当然,这个手续费等级是可以通过 UNI 治理随时更新的。在交易池价格区间设定上,根据 Uniswap v1 和 Uniswap v2 协议能够给出得实际交易价格区间都是 (0, ∞ ),这带来了一些问题,那就是当提供对像类似 USDC/USDT 这样的稳定币的流动性时,这样的机制设定会让 LP 的资金利用效率变得极为低下,因为稳定币中的价格交易区间几乎都是在一个非常小的范围内;所以,Uniswap v3 提供了更为灵活的价格设定机制,它允许用户根据目标代币的价格变化自行设定一个自己所提供的交易对的交易范围价格,这就让代币在任何价位内都能有合适的 LP,换句话说,大家都可以根据自己对于目标标的的认知来获取自己的利益了。在交易对支持上,Uniswap v1 只支持原生 ETH 作为桥接代币。比如:某人想要给代币 A 和 代币 B 这个交易对提供流动性,在 Uniswap v1 协议下,要完成这样的流动性提供,LP 实际上需要提供得是 ETH/A 和 ETH/B,这样处理的好处就是路由比较简单,但对 LP 来说成本会比较高,因为一般代币对都需要使用两次 ETH 来做桥接,这意味着两倍的流程费用同时承受着两倍的交易滑点;Uniswap v2 和 Uniswap v3 则允许 LP 为任意两个 ERC-20 代币创建交易合约,这一方面减少了交易流程费用和滑点,另一方面也大大增加了 LP 所能提供的代币对的种类,不足之处就是寻找最佳路由变得困难了,但这可以通过各种各样的链上聚合器来实现寻找最佳交易路径,类似于 1inch 就是这样的聚合器。其实除了交易手续费、交易价格区间设定和交易对支持这三方面之外, Uniswap v2 和 Uniswap v3 的具体内容还是非常丰富的,一篇篇幅较短的文章是不容易说得那么清楚的,详细内容还请大家移步 Uniswap v2 和 Uniswap v3 白皮书做更多全面了解。本人水平有限,我这里只是把我所理解的 Uniswap v2 和 Uniswap v3 的一些核心内容给大家做下汇报。https://uniswap.org/whitepaper.pdf ( https://uniswap.org/whitepaper.pdf ) 《uniswap v2 白皮书》https://uniswap.org/whitepaper-v3.pdf ( https://uniswap.org/whitepaper-v3.pdf ) 《uniswap v3 白皮书》3Uniswap v4 协议看点我们终于要聊到 Uniswap v4 了,前面啰嗦了那些东西也是为了更好更快让我们理解 Uniswap v4 在协议上的一些升级和创新点。目前 Uniswap 官方已经提前放出了 Uniswap v4 可能的一些变化,前期版本代码也已经开源,但并未最终发布上线,因为 Uniswap 官方给了几个月时间让广大的开发者参与共建。https://github.com/Uniswap/v4-core/blob/main/whitepaper-v4-draft.pdf ( https://github.com/Uniswap/v4-core/blob/main/whitepaper-v4-draft.pdf ) 《Uniswap v4 白皮书》根据白皮书的内容,我看到 Uniswap v4 有两大亮点,分别是:钩子和 gas 费用优化。3.1钩子在此前的所有 Uniswap 协议版本中,所有交易池子的生命周期都是紧密耦合在一起的,换句话说,设定任何池子之后,所有操作都会按照协议既定程序走完;而 Uniswap v4 允许用户创建一个钩子合约实现自定义流动性池子,也就是说,Uniswap v4 协议允许用户通过一种合约让流动性池子在其生命周期的任何节点执行某种特定的操作。就比如输入「钩子」,让这些用户可以自定义流动性池、兑换、费用和 LP 头寸。在官方说明中,他们给出了一些有趣的玩法的方向,比如:时间加权平均做市商(TWAMM)基于波动性或其他投入的动态费用链上限价订单将超出范围的流动性存入借贷协议定制化的链上预言机,例如几何平均数预言机自动复利 LP 手续费到 LP 头寸内部化的 MEV 利润分配给 LP基于波动性或其他投入的动态费用以及将超出范围的流动性存入借贷协议,我们根据上文中对之前协议的描述可以知道,Uniswap v4 协议之前的协议整体上的资金利用效率是在逐步提高的,但引入动态费用之后,LP 的资金利用效率会进一步得到提到。因为在实际交易过程中,会面临各种各样的复杂情况,每个交易对内的资产如果没有一个实时适应的反映就很难实现资金的最优化配置,Uniswap v4 通过动态费用以及将超出范围的流动性存入借贷协议补足了这个缺陷。而链上限价订单则有利于 Uniswap 争取到 cex 上的一些订单流,这可以进一步扩大 Uniswap 的订单量。自动复利 LP 手续费到 LP 头寸就是说产生的手续费用会自动投入到流动性池子中,这就像滚雪球一样,会让池子内的交易对规模越来越大,而此前的 Uniswap v3 不是这样的,它就是单纯的手续费而不会自动投入到池子中。...总的来说,引入钩子之后的玩法不仅限于上述官方给出的几种,钩子合约是用户自行编写的,理论上可玩性是无限的,这就有赖于广大用户无穷的想象力了。3.2gas 费用优化由于此前的协议会为每个流动性池子单独创建一个合约,这导致不同池子之间的路由总是会因为合约交互而产生一定的费用。Uniswap v4 在这方面的改进措施就是把所有流动性池子都用一个合约来管理,这就减少了不同合约交互这部分的 gas。据官方估计,Uniswap v4 仅利用这一个措施就将创建流动性池子池子的 gas 降低了 99%,不知道实际表现如何,我们可以期待下。除此之外,在「快速记账」系统方面也有了一定升级,在 Uniswap v3 中,所有的交易结算都是在净余额的基础上记录的,而 Uniswap v4 是在每次兑换结束时将资产转入和转出流动性池,这样就更加高效和简单明了,同时也因高效节省了一部分 gas。同时,Uniswap v4 又重新恢复了对原生 ETH 的交易支持,此前只有 Uniswap v1 支持支持原生 ETH,Uniswap v2 和 Uniswap v3 支持的是 WETH「一种包装后的 ETH 」,那么减少包装这个过程,当然也会节省一部分 gas 了。当我看到 Uniswap v4 在这些方面的改进点之后,我意识到 Uniswap v4 能够有利于 Uniswap 继续巩固自己作为 DIFI 龙头的地位,因为 Uniswap v4 通过钩子合约提供了更多可玩空间;而节省 gas 则是广大用户的需要,有利于接下来从 dex 聚合器手中回流一部分用户,而链上限价订单的支持则有助于 Uniswap 作为去中心化交易平台提升相对于中心化交易平台的竞争力。Uniswap v4 又一次给 DIFI 赛道带来了新的刺激,或许会对整个赛道产生不小的影响。顺便提一下,uni 代币自 6 月 13 日 Uniswap 官宣 v4 协议动作至今已有 20% 的涨幅,而 DIFI 赛道其他币种也有不同程度的上涨,这是否有关联?看完本文,大家或许会有自己的判断。不论如何,做任何投资决策前,请自行 DYOR 「做自己的研究」。这四个字母的意思是我前段时间才知道的,就也向大家报告一下~温馨提示:本号所有文章均在个人微信公众号「沈志强」首发,如需第一时间收到文章推送,可关注一下账号,我在那儿等您~发布于 2023-12-25 22:42赞同 2添加评论分享收藏喜欢
对比 Uniswap,一种新的去中心化交易所的流动性算法 | 登链社区 | 区块链技术社区
对比 Uniswap,一种新的去中心化交易所的流动性算法 | 登链社区 | 区块链技术社区
文章
问答
讲堂
专栏
集市
更多
提问
发表文章
活动
文档
招聘
发现
Toggle navigation
首页 (current)
文章
问答
讲堂
专栏
活动
招聘
文档
集市
搜索
登录/注册
对比 Uniswap,一种新的去中心化交易所的流动性算法
Phi·Wallet
更新于 2023-10-20 09:53
阅读 974
不同于 Uniswap的一种新的去中心化交易所的流动性算法
BY he.d.d.shan@hotmail.com
**注意:**
1. 本文的结论,有些是测试过的,有些是理论推导的。
2. 本文的读者最好了解 Uniswap 的恒定乘积理论。
## **Uniswap 的算法**
这里简单回顾一下 [Uniswap](https://learnblockchain.cn/article/2357) 的 [流动性](https://learnblockchain.cn/article/2448) 恒等 式 算法 。为 了简化,以UniswapV1 V2 来说明。
对于交易对 TokenA=>TokenB,对应的流动资金是 X 和 Y,则 **X\*Y=K**,当交易的时候,X 或 Y 会发生变化,K 值不变。
假设当初的流动性是 X0 和 Y0,用户支付 dY 数量的 TokenB 购买 x 数量的TokenA,则需要满足流动性性公式:X0 * Y0 =(X0 - x)* (Y0 + dY),可以推导出
x =X0 -(X0 * Y0 )/ (Y0 + dY)- X0=(X0* dY)/ (Y0 + dY)
即(公式 1) **x =(X0\* dY)/ (Y0 + dY)**
## **何氏新算法(连续价格理论)**
核心逻辑是:不使用 x*y=k 来推导交易数量,而是使用价格来推导。
在购买后,价格有两种表现形式,购买的价格是: **bPrice = x / dY**;而剩余流动性资金的价格是:**lPrice=(X0-x)/ (Y0+dy)**。当然**这两个价格是一样的(这就是核心**),则有 x / dY = (X0-x)/ (Y0+dy),可以推导出
x * (Y0+dy) = (X0-x)* dY
即(公式 2) **x =(X0\* dY)/ (Y0 +** **2 \*** **dY)**
这么个算法,有人考虑到了吗?我在中文社区没看见有人提出这个算法。其他出名的DEX也没采用这个算法,例如PancakeSwap、dXdY等。
## **何氏算法(连续价格理论)扩展一下**
如果存在一个交易池,里面有 TokenA,TokenB,TokenC,是不是可以交易这三个 Token 中的任意交易对?那是肯定的。
这种情况就存在一个问题,当交易 TokenA 和 TokenB 的时候,另外两个交易对 TokenA=>TokenC, TokenB=>TokenC,根本就没有发生交易,但价格变
化了(一个升高,一个降低),因为对应池子中的 TokenA 和 TokenB 变化了。
那这种情况是合理呢,还是不合理?
合不合理,又要对照 Uniswap 来说:
在 Uniswap 中 , 存在交易对 TokenA=>TokenB, TokenB=>TokenC,
TokenC=>TokenA,如果交易对 TokenC=>TokenA 发生了交易,则在交易对闭环(TokenB=>TokenC, TokenC=>TokenA,TokenA=>TokenB)中存在套
利机会,这里我不展开说,做过套利的朋友一眼就明白,对此不太明白的朋友可以查询一下相关资料。
套利的结果 ,就是通过路径 TokenA=>TokenB=>TokenC(三个交易对)得到的 TokenA 和 TokenC 的比价,和交易对 TokenA=>TokenC(这一个交易对)的比价,是一样的,最后导致 TokenB 的价格相对 TokenA 和 TokenB 都变化了(一个上涨,一个下跌)。这里忽略了手续费,但不影响逻辑。
所以说,**使用新算法的交易池,交易 TokenA 和 TokenC,导致 TokenB 相对 TokenA 和 TokenB 的价格变化是合理的**。
那么,四个 Token 组成的交易池,能否行得通呢?答案是肯定的,五个六个也可以的。
另外,相对于 Uniswap,其流动性值的定义也有改变,在本算法中更类似于UniswapV1 V2 的定义,是一种权重。
## **何氏算法(连续价格理论)的一些意义**
**1,可以规避内部套利**
新算法规避了内部的套利。这个在上面说过了。
而 Uniswap 的内部套利很严重,造成大量的套利交易,增加了 Gas 费用,我个人觉得对以太坊生态有一定的负面影响。
极端的看,如果以太坊只有一个使用此算法的去中心化交易所,这个交易所的交易池囊括了所有的 Token,例如 200 个 Token,那以太坊上就不存在套利机会了(当然跨链的套利机会是另外一回事)。
**2,提高资金利用率**
在多 Token 交易池,一个 Token 对应多个 Token 交易对,那这个 Token 的资金利用率相对 Uniswap 在理论上就提高了。
**3,降低流动性提供者的无常损失**
相对于 Uniswap 的公式 1,本算法的公式 2,加快了价格的下降幅度,相当于减少了无常损失,增加了流动性提供者的利润。
当然,这个属于理论上增加利润的一个因素。实际上的利润和很多因素有关,这里不展开说。
## **我的计划**
1. 找个时间,把这个算法提交给 Uniswap,看看他们怎么说。如果能被Uniswap 采用最好。
2. 如果有必要,我就写一套代码出来,包括合约和客户端,来测试和演示这套想法。我的合约代码可能做不到Uniswap的那种完美,但能够保证安全和计算正确,能做到商业化水平。
## **算法的可能改进**
1. 单独 Token 添加流动性。如果池子里面有 30 种 Token,难道用户要一次性添加 30种 Token 吗?这肯定不合常理。应该可以添加任意种 Token 就可以了,包括只添加一种 Token。
2. 流动性的计算,主要是价格的计算,需要使流动性对应的 Token 数量“虚化”、“样本化”或“分片化”,类似 UniswapV3 的做法,强调某个区间上的流动性分布,这样就能分离各个 Token 的实际数量和价格的对应关系了,使单个 Token 的添加流动性成为可能。
3. 各个交易对的手续费统一最简单。但是不统一呢?可以设置一个手续费等级,一等、二等。一等和一等的 Token 交易手续费是 3;一等和二等、二等和二等的是 5。方法很多,我这里只是列举这种方法。
update by 2023-10-20 小调整,主要是改善了几句话。
BY he.d.d.shan@hotmail.com
注意:
本文的结论,有些是测试过的,有些是理论推导的。
本文的读者最好了解 Uniswap 的恒定乘积理论。
Uniswap 的算法
这里简单回顾一下 Uniswap 的 流动性 恒等 式 算法 。为 了简化,以UniswapV1 V2 来说明。
对于交易对 TokenA=>TokenB,对应的流动资金是 X 和 Y,则 X*Y=K,当交易的时候,X 或 Y 会发生变化,K 值不变。
假设当初的流动性是 X0 和 Y0,用户支付 dY 数量的 TokenB 购买 x 数量的TokenA,则需要满足流动性性公式:X0 Y0 =(X0 - x) (Y0 + dY),可以推导出
x =X0 -(X0 Y0 )/ (Y0 + dY)- X0=(X0 dY)/ (Y0 + dY)
即(公式 1) x =(X0* dY)/ (Y0 + dY)
何氏新算法(连续价格理论)
核心逻辑是:不使用 x*y=k 来推导交易数量,而是使用价格来推导。
在购买后,价格有两种表现形式,购买的价格是: bPrice = x / dY;而剩余流动性资金的价格是:lPrice=(X0-x)/ (Y0+dy)。当然这两个价格是一样的(这就是核心),则有 x / dY = (X0-x)/ (Y0+dy),可以推导出
x (Y0+dy) = (X0-x) dY
即(公式 2) x =(X0* dY)/ (Y0 + 2 * dY)
这么个算法,有人考虑到了吗?我在中文社区没看见有人提出这个算法。其他出名的DEX也没采用这个算法,例如PancakeSwap、dXdY等。
何氏算法(连续价格理论)扩展一下
如果存在一个交易池,里面有 TokenA,TokenB,TokenC,是不是可以交易这三个 Token 中的任意交易对?那是肯定的。
这种情况就存在一个问题,当交易 TokenA 和 TokenB 的时候,另外两个交易对 TokenA=>TokenC, TokenB=>TokenC,根本就没有发生交易,但价格变
化了(一个升高,一个降低),因为对应池子中的 TokenA 和 TokenB 变化了。
那这种情况是合理呢,还是不合理?
合不合理,又要对照 Uniswap 来说:
在 Uniswap 中 , 存在交易对 TokenA=>TokenB, TokenB=>TokenC,
TokenC=>TokenA,如果交易对 TokenC=>TokenA 发生了交易,则在交易对闭环(TokenB=>TokenC, TokenC=>TokenA,TokenA=>TokenB)中存在套
利机会,这里我不展开说,做过套利的朋友一眼就明白,对此不太明白的朋友可以查询一下相关资料。
套利的结果 ,就是通过路径 TokenA=>TokenB=>TokenC(三个交易对)得到的 TokenA 和 TokenC 的比价,和交易对 TokenA=>TokenC(这一个交易对)的比价,是一样的,最后导致 TokenB 的价格相对 TokenA 和 TokenB 都变化了(一个上涨,一个下跌)。这里忽略了手续费,但不影响逻辑。
所以说,使用新算法的交易池,交易 TokenA 和 TokenC,导致 TokenB 相对 TokenA 和 TokenB 的价格变化是合理的。
那么,四个 Token 组成的交易池,能否行得通呢?答案是肯定的,五个六个也可以的。
另外,相对于 Uniswap,其流动性值的定义也有改变,在本算法中更类似于UniswapV1 V2 的定义,是一种权重。
何氏算法(连续价格理论)的一些意义
1,可以规避内部套利
新算法规避了内部的套利。这个在上面说过了。
而 Uniswap 的内部套利很严重,造成大量的套利交易,增加了 Gas 费用,我个人觉得对以太坊生态有一定的负面影响。
极端的看,如果以太坊只有一个使用此算法的去中心化交易所,这个交易所的交易池囊括了所有的 Token,例如 200 个 Token,那以太坊上就不存在套利机会了(当然跨链的套利机会是另外一回事)。
2,提高资金利用率
在多 Token 交易池,一个 Token 对应多个 Token 交易对,那这个 Token 的资金利用率相对 Uniswap 在理论上就提高了。
3,降低流动性提供者的无常损失
相对于 Uniswap 的公式 1,本算法的公式 2,加快了价格的下降幅度,相当于减少了无常损失,增加了流动性提供者的利润。
当然,这个属于理论上增加利润的一个因素。实际上的利润和很多因素有关,这里不展开说。
我的计划
找个时间,把这个算法提交给 Uniswap,看看他们怎么说。如果能被Uniswap 采用最好。
如果有必要,我就写一套代码出来,包括合约和客户端,来测试和演示这套想法。我的合约代码可能做不到Uniswap的那种完美,但能够保证安全和计算正确,能做到商业化水平。
算法的可能改进
单独 Token 添加流动性。如果池子里面有 30 种 Token,难道用户要一次性添加 30种 Token 吗?这肯定不合常理。应该可以添加任意种 Token 就可以了,包括只添加一种 Token。
流动性的计算,主要是价格的计算,需要使流动性对应的 Token 数量“虚化”、“样本化”或“分片化”,类似 UniswapV3 的做法,强调某个区间上的流动性分布,这样就能分离各个 Token 的实际数量和价格的对应关系了,使单个 Token 的添加流动性成为可能。
各个交易对的手续费统一最简单。但是不统一呢?可以设置一个手续费等级,一等、二等。一等和一等的 Token 交易手续费是 3;一等和二等、二等和二等的是 5。方法很多,我这里只是列举这种方法。
update by 2023-10-20 小调整,主要是改善了几句话。
原创
学分: 45
分类: DeFi
标签:
DEX
Uniswap
流动性
本文已由作者铸造成 NFT
网络:
Polygon
合约地址:
0x6f772e254Ef50e9b462915b66404009c73766350
IPFS hash:
QmRmSr7evi6WrE2Xbwq4EYzgPhLt7N2oFvutyKrZQXGAW4
查看TA的链上存证
点赞 4
收藏 3
分享
Twitter分享
微信扫码分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
你可能感兴趣的文章
UniswapV3 部署 - - Foundry Edition
233 浏览
无中转,无滑点,没有无常损失,低GAS,按角色分佣-TTSWAP去中心交易所-原理讲解(第一部份)
112 浏览
uniswap v2
313 浏览
图解跨链桥THORChain第三次攻击的攻击过程和POC
930 浏览
图解Sentiment安全攻击过程和写POC全过程
725 浏览
图解Platypus借贷漏洞的攻击过程和POC
824 浏览
相关问题
UniswapV3的router是不是在sepolia以及op,arb的sepolia实现exactInputSingle不一样了?
2 回答
我想通过流动性池的swap来直接交易代币,不知道为什么老是失败
1 回答
有没有已经部署的合约去查询Uniswap V3 NFT仓位的价值
1 回答
一般在编写套利合约中通过什么能直接读取给定交易对uniswap v2中的价格?
4 回答
uniswap 多跳路由寻找相关
1 回答
一个合约文件里面有多个合约方法 执行合约时要怎么做到执行指定的合约
2 回答
2 条评论
请先 登录 后评论
Phi·Wallet
关注
贡献值: 227
学分: 40
做各类基于以太坊的DAPP和数字资产交易所
文章目录
关于
关于我们
社区公约
学分规则
Github
伙伴们
DeCert
ChainTool
GCC
合作
广告投放
发布课程
联系我们
友情链接
关注社区
Discord
Youtube
B 站
公众号
关注不错过动态
微信群
加入技术圈子
©2024 登链社区 版权所有 |
Powered By Tipask3.5|
粤公网安备 44049102496617号
粤ICP备17140514号
粤B2-20230927
增值电信业务经营许可证
×
发送私信
请将文档链接发给晓娜,我们会尽快安排上架,感谢您的推荐!
发给:
内容:
取消
发送
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
取消
举报
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!
一文看懂Uniswap和Sushiswap - 知乎
一文看懂Uniswap和Sushiswap - 知乎首发于链习生切换模式写文章登录/注册一文看懂Uniswap和Sushiswap蒋梦初交易所历来是区块链领域的兵家必争之地,而去中心化交易所(DEX)则是本次DeFi热潮的主要赛道之一。从势如破竹的去中心化交易所Uniswap,到近几天名声大噪的赛场新星Sushiswap,一场“swap party”变得越发热闹。今天我们来讲讲这两个DEX,看看它们的异同。本文主要内容包括以下6点:l Uniswap和Sushiswap概况;l 这两家DEX的自动做市商(AMM)原理;l Uniswap的激励机制;l Sushiswap的激励机制;l Sushiswap的早期引流方法;l 这二者的风险。Uniswap和Sushiswap概况Uniswap是一家去中心化交易所(DEX),用来进行代币兑换。Uniswap是一个运行在以太坊区块链上的流动性协议,也就是一组部署到以太坊网络的合约,所有的交易都在链上进行。它不仅跟传统的加密货币交易所不同,也跟普通的去中心化代币交易所不同。它和上述交易所最大的不同就在于,它是基于兑换池,而不是订单簿的去中心化交易协议。在这里没有限价的买单卖单,用户与兑换池按照实时的市价进行交易,见下图。所谓的兑换池,指的是一个资金池,用户把一定量的token充入资金池,就可以兑换出同等价格的另一种token。在兑换过程中,交易所收取0.3%的手续费。用户在Uniswap中交易的价格则由这个资金池中的代币比例和算法来决定。这个算法是自动做市商(AMM),后文会详细讲。订单簿兑换池Uniswap在2019年就已经上线,现在它已经是头号DEX了。 Sushiswap也是一家去中心化交易所(DEX),用来进行代币兑换。目前Sushiswap尚未完全启动,在它完全启动后,它实现的功能与Uniswap相同。Sushi是日语寿司的意思,所以有人把这个项目叫寿司。寿司店(sushiswap)菜单Sushiswap协议是今年8月底才从Uniswap分叉而来,它基本延续Uniswap的核心设计,没有构建全新的模式,同样也是采用兑换池+自动做市商(AMM)的模式。另外,Sushiswap的代币池和前端页面设计与Uniswap也基本相同。自动做市商原理上文说过,Uniswap和Sushiswap都是采用基于兑换池的交易协议,依靠自动做市商模式来实现兑换,现在详细讲讲自动做市商(AMM)的原理。Uniswap并不使用订单簿模式来决定代币的价格,相反,代币的价格(汇率)会在用户交易的过程中连续且自动地根据供需量和恒定乘积公式计算得出。恒定乘积公式就是:X*Y=K。其中X和Y分别代表交易池中两种代币的可用数量。配合恒定乘积公式,一个交易对(也即一个流动性兑换池)中的一种代币的价格,根据池中的供给量和交易者的需求量得出,价格会在根据该公式画出的一条曲线上变动。X*Y=K,或者说Y=K/X,就是我们初中学过的反比例函数。当K不变时,X增大,Y必然减小,反之亦然。在DEX里,用户向兑换池中充入token X,X的数量增多了,Y的数量必然减小,而这减少的Y的数量就被用户取出,完成兑换。举例:假设流动性兑换池中有X token1000个,Y token100个,也就是10个X换1个Y。一名用户向兑换池中充入10个X,根据恒定乘积公式计算Y≈99,Y末-Y初=-1,这减少的1个Y就由这个用户拿走,实现了10个X兑换1个Y。AMM原理示例S在实际的Uniswap兑换过程中,还存在滑点的现象。滑点是指用户最终实现兑换的汇率偏离了真实的汇率。比如在上面的例子中,如果用户充500个X,他只能换出33.3个Y,相当于15个X才能换一个Y,用户就要承受损失。当兑换金额相对于兑换池资金量过大,或者说对于一定的兑换金额,兑换池资金太少时,就会出现滑点。但当兑换池中的代币数量充足时,滑点的数额就会减少,而且资金越多,滑点越小。滑点的大小和常说的交易深度大小相反,滑点越小,交易深度越大,用户越能够按照稳定的价格完成交易。同一时刻,ETH兑换LINK,兑换金额太大产生滑点恒定乘积公式的K越大,也就是资金池里的资金越多时,代币交换滑点越小,流动性也就越好。在这里的流动性就是指当用户想完成某一笔兑换时,他就能够在滑点最小的情况下顺利地完成。AMM模式鼓励用户为兑换资金池提供流动性,方式就是用户向流动性资金池中存入等价值的2种代币,比如上面例子里,用户同时存入100个X和10个Y。如果用户存入的2种代币不等值,比如他存入了100个X和100个Y,(此时的市价还是10个X换1个Y)这会造成兑换池里Y的供给相对过剩,X和Y的相对价值就出现了不平衡。套利者灵机一动,向兑换池里存入383.3个X,兑换出51.7个Y,而按照市价他只能换38.33个Y,于是他净赚13.37个Y。兑换池在经过套利者的一番操作后,又恢复了10个X换1个Y的市价,详情见下表。套利使系统重新归于平衡依靠恒定乘积公式的AMM模式需要套利交易来让流动性池中的代币价格与市场价格保持一致。从本质上来说,这些协议依然需要通过外部交易系统来调控流动性兑换池中代币的价格。AMM模式依靠用户为资金池提供流动性完成自动做市,它给用户的激励就是一定比例的兑换手续费。为流动性资金池提供流动性的用户称为流动性提供者(LP Liquidity Provider)。Uniswap的经济激励机制Uniswap给流动性提供者的奖励就是交易所的手续费。流动性提供者可以得到所在流动性池中代币交易的手续费作为奖励,手续费率为0.3%,流动性提供者之间依据存入资金的份额按比例分配。根据上文截图中的数据计算,一天的成交额是40.85亿CNY,一天的手续费就有122万元,经过一段时间的积累,流动性提供者(LP)得到的手续费奖励金额就非常可观了。Uniswap会根据流动性提供者存入资金的数额发给他们一定数量的LP token,我们可以理解为存款奖状或者收据,它是LP获得交易所手续费奖励的凭证。注意:LP token不是Uniswap的项目代币或者说平台币,对于每一种代币交易对有不同的LP token。举个例子具体说明:假设这个交易对是ETH--DAI,目前兑换比例是1ETH--400DAI。我向资金池充了1ETH和400DAI,这个资金池发给我1个LP token,代表我有1份(ETH--DAI)的流动性贡献。这个资金池所产生的手续费进入一个pool,经过一段时间后,pool中共有积累的手续费A个ETH和B个DAI,当我把我的1个LP token交还给Uniswap时,我有权利从pool拿走它按比例对应的手续费。假设此时整个资金池共发出了X个LP token,我的流动性贡献占比就是1/X,我就可以获得A/X个ETH和B/X个DAI,然后再赎回我的1ETH和400DAI。Uniswap通过AMM模式和为流动性提供者奖励手续费的模式,极大地调动了LP的积极性。由于任何人都可以提供流动性并且从中获利,人们有动力为Uniswap提供流动性;交易所获得充足的交易流动性,交易滑点就小,用户体验也好。交易所的运行完全基于市场的需求进行。人工的运维成本大幅降低。在Uniswap中,交易产品的挂牌会是免费的。而且由于不需要再用交易订单的模式,而且流动性也不需要专门的做市商来提供,因此目前证券市场中的做市商的成本就可以取消。降低了上币成本和做市成本,Uniswap对DeFi和整个区块链行业的发展起到了一定的促进作用。为Uniswap提供流动性的用户可以获得经济激励。不过,这种激励存在两个美中不足之处:1)对早期参与流动性提供的用户不够公平。Uniswap能够运转,全凭流动性提供者为它提供了大量的流动性。早期流动性提供者承担了更多的风险,但并没有因此获得更多的收益。Uniswap依靠着早期的LP存入的资金逐步发展,随着它越来越受欢迎,有越来越多的像风投基金、交易所、矿池这样的大资金进入提供流动性。虽然交易手续费累计的很多,但是早期LP的份额被摊薄了,他们没有能够享受到协议成长带来的长期回报。这有点像早期的滴滴司机或者淘宝店主,正是他们让平台实现了发展,然而在平台发展之后他们并没有享受到更多的收益。此外,流动性提供者只有在他们提供流动性时才赚取资金池的交易费。一旦他们撤回资金池中自己的资金,将不再获得相应的收入。2)无常损失得不到补偿。为Uniswap提供流动性可以交易手续费,但也存在无常损失。无偿损失是指流动性提供者按当时的市价存入2种代币,在他要取出这些代币时,它们的兑换价格发生了变化而导致的损失。如果这2种代币中某个代币大幅上涨或下跌都可能导致无常损失。注意,不管涨还是跌,都有可能导致损失。还是以上面表格里的X和Y为例。当10个X换1个Y时,我存入100X和10Y。假设现在行情变化,也就是X和Y的兑换比例变化了:不管现在是10个X换2个Y(Y跌了),还是20个X换1个Y(Y涨了),我如果想赎回我的资金,都必须按照现在的兑换比例,取出价格相等的X和Y,不能破坏资金池中2种代币的比例平衡,不然套利者就又要出动了。这也就是说,我取出来的不是我存入的100X和10Y,而是按照新的市价的兑换比例,比如120X和8Y。而这相比我直接持有100X和10Y不动,是会产生损失的。当然,它本质上也是资产的再平衡,从这个角度看,不算是无常损失。不过,在退出时,如果按照法币计价,可能会出现获得的费用收益不如直接持有代币所得的收益更高的现象。而且这个无常损失,是无偿的损失。Sushiswap的经济激励机制Sushiswap在Uniswap的激励机制基础上做出了一些改变,这是它们二者最大的区别。Sushiswap增加了代币经济激励,也就是将其交易费用的一部分分配给Sushiswap代币SUSHI的持有人。Uniswap没有发行平台币,它每笔交易收0.3%的手续费,再通过LP token的形式把交易费按比例分配给LP(流动性提供者)。Sushiswap发行了平台币SUSHI,它的交易手续费也是0.3%。它将这0.3%的手续费分成2个部分,其中0.25%提供给LP,方法和Uniswap一样;剩下的0.05%将用于回购SUSHI代币,即用这部分钱购买SUSHI代币持有者手里的SUSHI代币。这意味着,SUSHI的价值与Sushiswap平台交易量是挂钩的。在Sushiswap上,交易量越大,SUSHI捕获的价值就越高。SUSHI代币和COMP、LEND、YFI一样,也可以在二级市场交易。此外,为了保证研发和运营的持续,有10%SUSHI代币会用于开发和未来的迭代、审计等。Sushiswap的经济激励机制在Uniswap的基础上做了改进,它保证了早期参与者的长期利益。Sushiswap每个区块将释放100枚SUSHI代币,会均分给所有支持的代币池,LP们还是根据流动性贡献来按比例获得SUSHI。和Uniswap用LP token的形式来分配手续费不同,LP token只有在存入代币对时才发给用户,而SUSHI是每个区块都产生一次,根据用户现在的资金比例分配。这样即使未来有大资金进入Sushiswap,早期参与者的资金份额被摊薄,但是他们之前已经获得的SUSHI代币不会减少,这就相当于是挖到了“头矿”。更何况在最初的100,000个区块,SUSHI产量更高,每个区块释放1,000枚SUSHI。在Sushiswap交易额增长起来后,SUSHI代币的价格也水涨船高,早期参与者凭借着早期相对较高资金份额占比而积累下的SUSHI代币可以享受到Sushiswap长期发展带来的福利。此外,前文提及,Uniswap的LP在赎回了当初存入的代币对之后,就不能再获得交易所的手续费分成了,而Sushiswap的LP即使赎回了资金,也还能够凭借着持有的SUSHI代币获得币价上涨带来的利益。Sushiswap的经济激励机制也并非尽善尽美。SUSHI代币有2个主要用途。第1点是用于投票。投票决定每个区块产生的100个SUSHI在各个代币对兑换池中分配的比例,也就是哪个池子分到的SUSHI奖励多一点;投票决定是不是要新开放某个新代币对兑换池。对于特定的LP来说,这2种投票的目的都是为了让自己获得更多的SUSHI奖励,消耗一部分SUSHI以获得更多的SUSHI。这样会不会造成分配权重大的资金池分配比例越来越大呢,还有待时间的检验。第2点就是上文说的用于兑换那0.05%的手续费。在交易所蒸蒸日上的阶段这当然是好的了,不过如果交易额下降呢。无限通货膨胀的SUSHI和正在下降的手续费分成相互作用,会导致新产生的SUSHI越来越不值钱,对币价下降的预期则会让老持币人竞相抛售。如果他们再从流动性资金池里撤资,交易所流动性不足,引起交易滑点过大,用户体验变差,交易额就会进一步下降。这样的恶性循环会迅速让它承受巨大损失。这样的情形不一定会出现,但是会有这样的风险。虽然在Uniswap中同样存在交易额下降引发流动性下降的恶性循环,不过它没有平台币,也就没有币价下降的第三重刺激。Sushiswap中同样存在无常损失。Sushiswap的大招仅靠改进的经济激励模型,能不能让Sushiswap超越老大哥,坐上DEX头把交椅呢,我们不得而知。不过项目方还想了别的办法,真正的大招还在后头呢。第一步。Sushiswap为Uniswap的流动性提供者提供了赚取SUSHI代币的机会。Uniswap的流动性提供者可以将其LP token质押在Sushiswap,然后在区块高度10750000开始赚取SUSHI代币。目前只收LP token,还不能直接存入代币对。这好比是你在一家大银行Uniswap存了钱,它发给你一个收据,凭此取钱。新银行Sushiswap说,你的收据质押在我这里,1星期以后我给你这张收据发利息,你的钱还在原来的银行,收据你想拿走随时拿走。这样的好事谁不干,于是大家纷纷把Uniswap的LP token质押在Sushiswap。只要LP token第二步。在协议启动大约两周(最初100,000个区块)后,Sushiswap会启动针对Uniswap的流动性池迁移计划。在迁移过程中,首先是这一批用户在Uniswap上进行代币对的赎回,然后将这些代币池迁移,也就是把从Uniswap里取出来的钱存到Sushiswap里。就这样,Sushiswap将获得大量的流动性,它的流动性是从Uniswap那里直接拿来的。近日Uniswap锁仓量(就是资金池的存款量)暴涨,原因就是Sushiswap只收Uniswap的LP token,用户必须先到Uniswap去存钱,换出LP token,才能把它质押到Sushiswap里。复制粘贴你的运行原理,剪切粘贴你的用户。SIGOI!(日语:好厉害)风险最后我们谈一谈这两家DEX的风险。l 技术风险Uniswap在2020年3月19日在以太坊主网上推出了一个新版本,还配合着公开了核心合约的1.0.1版;在发行之前,该版本已经在Rinkeby测试网上测试过一段时间了。这个新版本在以太坊主网上已经使用超过了两个月时间,而且迄今为止,没有出现任何损坏智能合约完整性的问题。Uniswap V2 在上线主网之前经过了充分的测试和审核。对源代码的尽职审核“很有可能”保证了未来不会发现任何重大的问题,不过Uniswap还是发布了一个Bug悬赏,任何人发现了重大漏洞都可以获得奖金。从Sushiswap宣布的信息看,它邀请Trail of Bits、PeckShield、OpenZeppelin、Consensys、Certik、Quantstamp中的其中一家对其合约进行审计。但目前为止还没有完成正式审计。这里是有潜在风险的。即便完成了审计,任何流动性挖矿都存在潜在的智能合约漏洞风险。编写出没有任何错误的代码是非常困难的,而开发人员也不可能设想到所有的潜在风险,尤其是在DeFi发展如此火爆的今天。Uniswap和Sushiswap都存在一定程度的技术风险。审计、测试以及购买智能合约保险都可以降低技术风险。l 经济模型风险许多区块链项目,特别是在DeFi领域,都需要依靠经济激励来激励网络的参与者。有时候经济模型看起来无懈可击,却包含着潜在的风险。对于这两家DEX的LP来说,首先要面对的就是上文所说无常损失风险。而且是为价格波动越大的币种提供流动性,出现无常损失的风险越高,这导致很多用户发现,为DEX提供流动性(也就是流动性挖矿)带来的收益还不如无常损失更多。SUSHI是每个区块产生100个,它与比特币、以太币等不一样。比特币只有2100万枚,而SUSHI是无限通货膨胀的,未来Sushiswap的交易额增长能够跑得过无限通胀呢,现在还没有一个明确的结论。交易额下降会不会引发流动性枯竭,造成恶性循环,这是它们都面临的风险。l 外部风险外部风险指的不是Uniswap和Sushiswap本身存在的风险,而是在它们上线的项目中存在的风险。例如:项目的虚假宣传、项目方大量抛售代币导致币价崩盘等等。只需要建立两个资金池,就可以无上币费、无审查、无成本地“三无上币”,大大降低了项目方发币割韭菜的难度和成本,这简直比2017年还疯狂。结语:以前说币圈一天,人间一年,现在是DeFi圈一天,币圈一年。这两家swap不是“swap party”的谢幕,还会有更多DEX和其他项目粉墨登场。希望各项目能够互相促进,共同为数字金融和区块链行业的发展助力。本文部分观点参考以下文章:有关Uniswap V2的一切:新功能与工作原理。www.8btc.com/article/641872火币观察:SUSHI飙涨行情耀眼,SushiSwap是否存在风险?www.jinse.com/news/blockchain/804917.html从Uniswap看未来的数字资产交易所。www.8btc.com/article/636431全维度深入解析:Uniswap的正面与背面。www.8btc.com/media/636300SushiSwap锁仓超10亿美元,赚钱效应成DeFi繁荣的最大推手。www.jinse.com/news/blockchain/805211.htmlSushiswap:Uniswap的进化?http://blog.csdn.net/lanhubiji/article/details/108289403作者:蒋梦初2020年9月4日编辑于 2020-09-08 21:50区块链(Blockchain)去中心化金融(DeFi)赞同 34020 条评论分享喜欢收藏申请转载文章被以下专栏收录链习生原创,区块链领域,通俗
一文看懂Uniswap和Sushiswap - 知乎
一文看懂Uniswap和Sushiswap - 知乎首发于链习生切换模式写文章登录/注册一文看懂Uniswap和Sushiswap蒋梦初交易所历来是区块链领域的兵家必争之地,而去中心化交易所(DEX)则是本次DeFi热潮的主要赛道之一。从势如破竹的去中心化交易所Uniswap,到近几天名声大噪的赛场新星Sushiswap,一场“swap party”变得越发热闹。今天我们来讲讲这两个DEX,看看它们的异同。本文主要内容包括以下6点:l Uniswap和Sushiswap概况;l 这两家DEX的自动做市商(AMM)原理;l Uniswap的激励机制;l Sushiswap的激励机制;l Sushiswap的早期引流方法;l 这二者的风险。Uniswap和Sushiswap概况Uniswap是一家去中心化交易所(DEX),用来进行代币兑换。Uniswap是一个运行在以太坊区块链上的流动性协议,也就是一组部署到以太坊网络的合约,所有的交易都在链上进行。它不仅跟传统的加密货币交易所不同,也跟普通的去中心化代币交易所不同。它和上述交易所最大的不同就在于,它是基于兑换池,而不是订单簿的去中心化交易协议。在这里没有限价的买单卖单,用户与兑换池按照实时的市价进行交易,见下图。所谓的兑换池,指的是一个资金池,用户把一定量的token充入资金池,就可以兑换出同等价格的另一种token。在兑换过程中,交易所收取0.3%的手续费。用户在Uniswap中交易的价格则由这个资金池中的代币比例和算法来决定。这个算法是自动做市商(AMM),后文会详细讲。订单簿兑换池Uniswap在2019年就已经上线,现在它已经是头号DEX了。 Sushiswap也是一家去中心化交易所(DEX),用来进行代币兑换。目前Sushiswap尚未完全启动,在它完全启动后,它实现的功能与Uniswap相同。Sushi是日语寿司的意思,所以有人把这个项目叫寿司。寿司店(sushiswap)菜单Sushiswap协议是今年8月底才从Uniswap分叉而来,它基本延续Uniswap的核心设计,没有构建全新的模式,同样也是采用兑换池+自动做市商(AMM)的模式。另外,Sushiswap的代币池和前端页面设计与Uniswap也基本相同。自动做市商原理上文说过,Uniswap和Sushiswap都是采用基于兑换池的交易协议,依靠自动做市商模式来实现兑换,现在详细讲讲自动做市商(AMM)的原理。Uniswap并不使用订单簿模式来决定代币的价格,相反,代币的价格(汇率)会在用户交易的过程中连续且自动地根据供需量和恒定乘积公式计算得出。恒定乘积公式就是:X*Y=K。其中X和Y分别代表交易池中两种代币的可用数量。配合恒定乘积公式,一个交易对(也即一个流动性兑换池)中的一种代币的价格,根据池中的供给量和交易者的需求量得出,价格会在根据该公式画出的一条曲线上变动。X*Y=K,或者说Y=K/X,就是我们初中学过的反比例函数。当K不变时,X增大,Y必然减小,反之亦然。在DEX里,用户向兑换池中充入token X,X的数量增多了,Y的数量必然减小,而这减少的Y的数量就被用户取出,完成兑换。举例:假设流动性兑换池中有X token1000个,Y token100个,也就是10个X换1个Y。一名用户向兑换池中充入10个X,根据恒定乘积公式计算Y≈99,Y末-Y初=-1,这减少的1个Y就由这个用户拿走,实现了10个X兑换1个Y。AMM原理示例S在实际的Uniswap兑换过程中,还存在滑点的现象。滑点是指用户最终实现兑换的汇率偏离了真实的汇率。比如在上面的例子中,如果用户充500个X,他只能换出33.3个Y,相当于15个X才能换一个Y,用户就要承受损失。当兑换金额相对于兑换池资金量过大,或者说对于一定的兑换金额,兑换池资金太少时,就会出现滑点。但当兑换池中的代币数量充足时,滑点的数额就会减少,而且资金越多,滑点越小。滑点的大小和常说的交易深度大小相反,滑点越小,交易深度越大,用户越能够按照稳定的价格完成交易。同一时刻,ETH兑换LINK,兑换金额太大产生滑点恒定乘积公式的K越大,也就是资金池里的资金越多时,代币交换滑点越小,流动性也就越好。在这里的流动性就是指当用户想完成某一笔兑换时,他就能够在滑点最小的情况下顺利地完成。AMM模式鼓励用户为兑换资金池提供流动性,方式就是用户向流动性资金池中存入等价值的2种代币,比如上面例子里,用户同时存入100个X和10个Y。如果用户存入的2种代币不等值,比如他存入了100个X和100个Y,(此时的市价还是10个X换1个Y)这会造成兑换池里Y的供给相对过剩,X和Y的相对价值就出现了不平衡。套利者灵机一动,向兑换池里存入383.3个X,兑换出51.7个Y,而按照市价他只能换38.33个Y,于是他净赚13.37个Y。兑换池在经过套利者的一番操作后,又恢复了10个X换1个Y的市价,详情见下表。套利使系统重新归于平衡依靠恒定乘积公式的AMM模式需要套利交易来让流动性池中的代币价格与市场价格保持一致。从本质上来说,这些协议依然需要通过外部交易系统来调控流动性兑换池中代币的价格。AMM模式依靠用户为资金池提供流动性完成自动做市,它给用户的激励就是一定比例的兑换手续费。为流动性资金池提供流动性的用户称为流动性提供者(LP Liquidity Provider)。Uniswap的经济激励机制Uniswap给流动性提供者的奖励就是交易所的手续费。流动性提供者可以得到所在流动性池中代币交易的手续费作为奖励,手续费率为0.3%,流动性提供者之间依据存入资金的份额按比例分配。根据上文截图中的数据计算,一天的成交额是40.85亿CNY,一天的手续费就有122万元,经过一段时间的积累,流动性提供者(LP)得到的手续费奖励金额就非常可观了。Uniswap会根据流动性提供者存入资金的数额发给他们一定数量的LP token,我们可以理解为存款奖状或者收据,它是LP获得交易所手续费奖励的凭证。注意:LP token不是Uniswap的项目代币或者说平台币,对于每一种代币交易对有不同的LP token。举个例子具体说明:假设这个交易对是ETH--DAI,目前兑换比例是1ETH--400DAI。我向资金池充了1ETH和400DAI,这个资金池发给我1个LP token,代表我有1份(ETH--DAI)的流动性贡献。这个资金池所产生的手续费进入一个pool,经过一段时间后,pool中共有积累的手续费A个ETH和B个DAI,当我把我的1个LP token交还给Uniswap时,我有权利从pool拿走它按比例对应的手续费。假设此时整个资金池共发出了X个LP token,我的流动性贡献占比就是1/X,我就可以获得A/X个ETH和B/X个DAI,然后再赎回我的1ETH和400DAI。Uniswap通过AMM模式和为流动性提供者奖励手续费的模式,极大地调动了LP的积极性。由于任何人都可以提供流动性并且从中获利,人们有动力为Uniswap提供流动性;交易所获得充足的交易流动性,交易滑点就小,用户体验也好。交易所的运行完全基于市场的需求进行。人工的运维成本大幅降低。在Uniswap中,交易产品的挂牌会是免费的。而且由于不需要再用交易订单的模式,而且流动性也不需要专门的做市商来提供,因此目前证券市场中的做市商的成本就可以取消。降低了上币成本和做市成本,Uniswap对DeFi和整个区块链行业的发展起到了一定的促进作用。为Uniswap提供流动性的用户可以获得经济激励。不过,这种激励存在两个美中不足之处:1)对早期参与流动性提供的用户不够公平。Uniswap能够运转,全凭流动性提供者为它提供了大量的流动性。早期流动性提供者承担了更多的风险,但并没有因此获得更多的收益。Uniswap依靠着早期的LP存入的资金逐步发展,随着它越来越受欢迎,有越来越多的像风投基金、交易所、矿池这样的大资金进入提供流动性。虽然交易手续费累计的很多,但是早期LP的份额被摊薄了,他们没有能够享受到协议成长带来的长期回报。这有点像早期的滴滴司机或者淘宝店主,正是他们让平台实现了发展,然而在平台发展之后他们并没有享受到更多的收益。此外,流动性提供者只有在他们提供流动性时才赚取资金池的交易费。一旦他们撤回资金池中自己的资金,将不再获得相应的收入。2)无常损失得不到补偿。为Uniswap提供流动性可以交易手续费,但也存在无常损失。无偿损失是指流动性提供者按当时的市价存入2种代币,在他要取出这些代币时,它们的兑换价格发生了变化而导致的损失。如果这2种代币中某个代币大幅上涨或下跌都可能导致无常损失。注意,不管涨还是跌,都有可能导致损失。还是以上面表格里的X和Y为例。当10个X换1个Y时,我存入100X和10Y。假设现在行情变化,也就是X和Y的兑换比例变化了:不管现在是10个X换2个Y(Y跌了),还是20个X换1个Y(Y涨了),我如果想赎回我的资金,都必须按照现在的兑换比例,取出价格相等的X和Y,不能破坏资金池中2种代币的比例平衡,不然套利者就又要出动了。这也就是说,我取出来的不是我存入的100X和10Y,而是按照新的市价的兑换比例,比如120X和8Y。而这相比我直接持有100X和10Y不动,是会产生损失的。当然,它本质上也是资产的再平衡,从这个角度看,不算是无常损失。不过,在退出时,如果按照法币计价,可能会出现获得的费用收益不如直接持有代币所得的收益更高的现象。而且这个无常损失,是无偿的损失。Sushiswap的经济激励机制Sushiswap在Uniswap的激励机制基础上做出了一些改变,这是它们二者最大的区别。Sushiswap增加了代币经济激励,也就是将其交易费用的一部分分配给Sushiswap代币SUSHI的持有人。Uniswap没有发行平台币,它每笔交易收0.3%的手续费,再通过LP token的形式把交易费按比例分配给LP(流动性提供者)。Sushiswap发行了平台币SUSHI,它的交易手续费也是0.3%。它将这0.3%的手续费分成2个部分,其中0.25%提供给LP,方法和Uniswap一样;剩下的0.05%将用于回购SUSHI代币,即用这部分钱购买SUSHI代币持有者手里的SUSHI代币。这意味着,SUSHI的价值与Sushiswap平台交易量是挂钩的。在Sushiswap上,交易量越大,SUSHI捕获的价值就越高。SUSHI代币和COMP、LEND、YFI一样,也可以在二级市场交易。此外,为了保证研发和运营的持续,有10%SUSHI代币会用于开发和未来的迭代、审计等。Sushiswap的经济激励机制在Uniswap的基础上做了改进,它保证了早期参与者的长期利益。Sushiswap每个区块将释放100枚SUSHI代币,会均分给所有支持的代币池,LP们还是根据流动性贡献来按比例获得SUSHI。和Uniswap用LP token的形式来分配手续费不同,LP token只有在存入代币对时才发给用户,而SUSHI是每个区块都产生一次,根据用户现在的资金比例分配。这样即使未来有大资金进入Sushiswap,早期参与者的资金份额被摊薄,但是他们之前已经获得的SUSHI代币不会减少,这就相当于是挖到了“头矿”。更何况在最初的100,000个区块,SUSHI产量更高,每个区块释放1,000枚SUSHI。在Sushiswap交易额增长起来后,SUSHI代币的价格也水涨船高,早期参与者凭借着早期相对较高资金份额占比而积累下的SUSHI代币可以享受到Sushiswap长期发展带来的福利。此外,前文提及,Uniswap的LP在赎回了当初存入的代币对之后,就不能再获得交易所的手续费分成了,而Sushiswap的LP即使赎回了资金,也还能够凭借着持有的SUSHI代币获得币价上涨带来的利益。Sushiswap的经济激励机制也并非尽善尽美。SUSHI代币有2个主要用途。第1点是用于投票。投票决定每个区块产生的100个SUSHI在各个代币对兑换池中分配的比例,也就是哪个池子分到的SUSHI奖励多一点;投票决定是不是要新开放某个新代币对兑换池。对于特定的LP来说,这2种投票的目的都是为了让自己获得更多的SUSHI奖励,消耗一部分SUSHI以获得更多的SUSHI。这样会不会造成分配权重大的资金池分配比例越来越大呢,还有待时间的检验。第2点就是上文说的用于兑换那0.05%的手续费。在交易所蒸蒸日上的阶段这当然是好的了,不过如果交易额下降呢。无限通货膨胀的SUSHI和正在下降的手续费分成相互作用,会导致新产生的SUSHI越来越不值钱,对币价下降的预期则会让老持币人竞相抛售。如果他们再从流动性资金池里撤资,交易所流动性不足,引起交易滑点过大,用户体验变差,交易额就会进一步下降。这样的恶性循环会迅速让它承受巨大损失。这样的情形不一定会出现,但是会有这样的风险。虽然在Uniswap中同样存在交易额下降引发流动性下降的恶性循环,不过它没有平台币,也就没有币价下降的第三重刺激。Sushiswap中同样存在无常损失。Sushiswap的大招仅靠改进的经济激励模型,能不能让Sushiswap超越老大哥,坐上DEX头把交椅呢,我们不得而知。不过项目方还想了别的办法,真正的大招还在后头呢。第一步。Sushiswap为Uniswap的流动性提供者提供了赚取SUSHI代币的机会。Uniswap的流动性提供者可以将其LP token质押在Sushiswap,然后在区块高度10750000开始赚取SUSHI代币。目前只收LP token,还不能直接存入代币对。这好比是你在一家大银行Uniswap存了钱,它发给你一个收据,凭此取钱。新银行Sushiswap说,你的收据质押在我这里,1星期以后我给你这张收据发利息,你的钱还在原来的银行,收据你想拿走随时拿走。这样的好事谁不干,于是大家纷纷把Uniswap的LP token质押在Sushiswap。只要LP token第二步。在协议启动大约两周(最初100,000个区块)后,Sushiswap会启动针对Uniswap的流动性池迁移计划。在迁移过程中,首先是这一批用户在Uniswap上进行代币对的赎回,然后将这些代币池迁移,也就是把从Uniswap里取出来的钱存到Sushiswap里。就这样,Sushiswap将获得大量的流动性,它的流动性是从Uniswap那里直接拿来的。近日Uniswap锁仓量(就是资金池的存款量)暴涨,原因就是Sushiswap只收Uniswap的LP token,用户必须先到Uniswap去存钱,换出LP token,才能把它质押到Sushiswap里。复制粘贴你的运行原理,剪切粘贴你的用户。SIGOI!(日语:好厉害)风险最后我们谈一谈这两家DEX的风险。l 技术风险Uniswap在2020年3月19日在以太坊主网上推出了一个新版本,还配合着公开了核心合约的1.0.1版;在发行之前,该版本已经在Rinkeby测试网上测试过一段时间了。这个新版本在以太坊主网上已经使用超过了两个月时间,而且迄今为止,没有出现任何损坏智能合约完整性的问题。Uniswap V2 在上线主网之前经过了充分的测试和审核。对源代码的尽职审核“很有可能”保证了未来不会发现任何重大的问题,不过Uniswap还是发布了一个Bug悬赏,任何人发现了重大漏洞都可以获得奖金。从Sushiswap宣布的信息看,它邀请Trail of Bits、PeckShield、OpenZeppelin、Consensys、Certik、Quantstamp中的其中一家对其合约进行审计。但目前为止还没有完成正式审计。这里是有潜在风险的。即便完成了审计,任何流动性挖矿都存在潜在的智能合约漏洞风险。编写出没有任何错误的代码是非常困难的,而开发人员也不可能设想到所有的潜在风险,尤其是在DeFi发展如此火爆的今天。Uniswap和Sushiswap都存在一定程度的技术风险。审计、测试以及购买智能合约保险都可以降低技术风险。l 经济模型风险许多区块链项目,特别是在DeFi领域,都需要依靠经济激励来激励网络的参与者。有时候经济模型看起来无懈可击,却包含着潜在的风险。对于这两家DEX的LP来说,首先要面对的就是上文所说无常损失风险。而且是为价格波动越大的币种提供流动性,出现无常损失的风险越高,这导致很多用户发现,为DEX提供流动性(也就是流动性挖矿)带来的收益还不如无常损失更多。SUSHI是每个区块产生100个,它与比特币、以太币等不一样。比特币只有2100万枚,而SUSHI是无限通货膨胀的,未来Sushiswap的交易额增长能够跑得过无限通胀呢,现在还没有一个明确的结论。交易额下降会不会引发流动性枯竭,造成恶性循环,这是它们都面临的风险。l 外部风险外部风险指的不是Uniswap和Sushiswap本身存在的风险,而是在它们上线的项目中存在的风险。例如:项目的虚假宣传、项目方大量抛售代币导致币价崩盘等等。只需要建立两个资金池,就可以无上币费、无审查、无成本地“三无上币”,大大降低了项目方发币割韭菜的难度和成本,这简直比2017年还疯狂。结语:以前说币圈一天,人间一年,现在是DeFi圈一天,币圈一年。这两家swap不是“swap party”的谢幕,还会有更多DEX和其他项目粉墨登场。希望各项目能够互相促进,共同为数字金融和区块链行业的发展助力。本文部分观点参考以下文章:有关Uniswap V2的一切:新功能与工作原理。www.8btc.com/article/641872火币观察:SUSHI飙涨行情耀眼,SushiSwap是否存在风险?www.jinse.com/news/blockchain/804917.html从Uniswap看未来的数字资产交易所。www.8btc.com/article/636431全维度深入解析:Uniswap的正面与背面。www.8btc.com/media/636300SushiSwap锁仓超10亿美元,赚钱效应成DeFi繁荣的最大推手。www.jinse.com/news/blockchain/805211.htmlSushiswap:Uniswap的进化?http://blog.csdn.net/lanhubiji/article/details/108289403作者:蒋梦初2020年9月4日编辑于 2020-09-08 21:50区块链(Blockchain)去中心化金融(DeFi)赞同 34020 条评论分享喜欢收藏申请转载文章被以下专栏收录链习生原创,区块链领域,通俗
一文看懂Uniswap和Sushiswap - 知乎
一文看懂Uniswap和Sushiswap - 知乎首发于链习生切换模式写文章登录/注册一文看懂Uniswap和Sushiswap蒋梦初交易所历来是区块链领域的兵家必争之地,而去中心化交易所(DEX)则是本次DeFi热潮的主要赛道之一。从势如破竹的去中心化交易所Uniswap,到近几天名声大噪的赛场新星Sushiswap,一场“swap party”变得越发热闹。今天我们来讲讲这两个DEX,看看它们的异同。本文主要内容包括以下6点:l Uniswap和Sushiswap概况;l 这两家DEX的自动做市商(AMM)原理;l Uniswap的激励机制;l Sushiswap的激励机制;l Sushiswap的早期引流方法;l 这二者的风险。Uniswap和Sushiswap概况Uniswap是一家去中心化交易所(DEX),用来进行代币兑换。Uniswap是一个运行在以太坊区块链上的流动性协议,也就是一组部署到以太坊网络的合约,所有的交易都在链上进行。它不仅跟传统的加密货币交易所不同,也跟普通的去中心化代币交易所不同。它和上述交易所最大的不同就在于,它是基于兑换池,而不是订单簿的去中心化交易协议。在这里没有限价的买单卖单,用户与兑换池按照实时的市价进行交易,见下图。所谓的兑换池,指的是一个资金池,用户把一定量的token充入资金池,就可以兑换出同等价格的另一种token。在兑换过程中,交易所收取0.3%的手续费。用户在Uniswap中交易的价格则由这个资金池中的代币比例和算法来决定。这个算法是自动做市商(AMM),后文会详细讲。订单簿兑换池Uniswap在2019年就已经上线,现在它已经是头号DEX了。 Sushiswap也是一家去中心化交易所(DEX),用来进行代币兑换。目前Sushiswap尚未完全启动,在它完全启动后,它实现的功能与Uniswap相同。Sushi是日语寿司的意思,所以有人把这个项目叫寿司。寿司店(sushiswap)菜单Sushiswap协议是今年8月底才从Uniswap分叉而来,它基本延续Uniswap的核心设计,没有构建全新的模式,同样也是采用兑换池+自动做市商(AMM)的模式。另外,Sushiswap的代币池和前端页面设计与Uniswap也基本相同。自动做市商原理上文说过,Uniswap和Sushiswap都是采用基于兑换池的交易协议,依靠自动做市商模式来实现兑换,现在详细讲讲自动做市商(AMM)的原理。Uniswap并不使用订单簿模式来决定代币的价格,相反,代币的价格(汇率)会在用户交易的过程中连续且自动地根据供需量和恒定乘积公式计算得出。恒定乘积公式就是:X*Y=K。其中X和Y分别代表交易池中两种代币的可用数量。配合恒定乘积公式,一个交易对(也即一个流动性兑换池)中的一种代币的价格,根据池中的供给量和交易者的需求量得出,价格会在根据该公式画出的一条曲线上变动。X*Y=K,或者说Y=K/X,就是我们初中学过的反比例函数。当K不变时,X增大,Y必然减小,反之亦然。在DEX里,用户向兑换池中充入token X,X的数量增多了,Y的数量必然减小,而这减少的Y的数量就被用户取出,完成兑换。举例:假设流动性兑换池中有X token1000个,Y token100个,也就是10个X换1个Y。一名用户向兑换池中充入10个X,根据恒定乘积公式计算Y≈99,Y末-Y初=-1,这减少的1个Y就由这个用户拿走,实现了10个X兑换1个Y。AMM原理示例S在实际的Uniswap兑换过程中,还存在滑点的现象。滑点是指用户最终实现兑换的汇率偏离了真实的汇率。比如在上面的例子中,如果用户充500个X,他只能换出33.3个Y,相当于15个X才能换一个Y,用户就要承受损失。当兑换金额相对于兑换池资金量过大,或者说对于一定的兑换金额,兑换池资金太少时,就会出现滑点。但当兑换池中的代币数量充足时,滑点的数额就会减少,而且资金越多,滑点越小。滑点的大小和常说的交易深度大小相反,滑点越小,交易深度越大,用户越能够按照稳定的价格完成交易。同一时刻,ETH兑换LINK,兑换金额太大产生滑点恒定乘积公式的K越大,也就是资金池里的资金越多时,代币交换滑点越小,流动性也就越好。在这里的流动性就是指当用户想完成某一笔兑换时,他就能够在滑点最小的情况下顺利地完成。AMM模式鼓励用户为兑换资金池提供流动性,方式就是用户向流动性资金池中存入等价值的2种代币,比如上面例子里,用户同时存入100个X和10个Y。如果用户存入的2种代币不等值,比如他存入了100个X和100个Y,(此时的市价还是10个X换1个Y)这会造成兑换池里Y的供给相对过剩,X和Y的相对价值就出现了不平衡。套利者灵机一动,向兑换池里存入383.3个X,兑换出51.7个Y,而按照市价他只能换38.33个Y,于是他净赚13.37个Y。兑换池在经过套利者的一番操作后,又恢复了10个X换1个Y的市价,详情见下表。套利使系统重新归于平衡依靠恒定乘积公式的AMM模式需要套利交易来让流动性池中的代币价格与市场价格保持一致。从本质上来说,这些协议依然需要通过外部交易系统来调控流动性兑换池中代币的价格。AMM模式依靠用户为资金池提供流动性完成自动做市,它给用户的激励就是一定比例的兑换手续费。为流动性资金池提供流动性的用户称为流动性提供者(LP Liquidity Provider)。Uniswap的经济激励机制Uniswap给流动性提供者的奖励就是交易所的手续费。流动性提供者可以得到所在流动性池中代币交易的手续费作为奖励,手续费率为0.3%,流动性提供者之间依据存入资金的份额按比例分配。根据上文截图中的数据计算,一天的成交额是40.85亿CNY,一天的手续费就有122万元,经过一段时间的积累,流动性提供者(LP)得到的手续费奖励金额就非常可观了。Uniswap会根据流动性提供者存入资金的数额发给他们一定数量的LP token,我们可以理解为存款奖状或者收据,它是LP获得交易所手续费奖励的凭证。注意:LP token不是Uniswap的项目代币或者说平台币,对于每一种代币交易对有不同的LP token。举个例子具体说明:假设这个交易对是ETH--DAI,目前兑换比例是1ETH--400DAI。我向资金池充了1ETH和400DAI,这个资金池发给我1个LP token,代表我有1份(ETH--DAI)的流动性贡献。这个资金池所产生的手续费进入一个pool,经过一段时间后,pool中共有积累的手续费A个ETH和B个DAI,当我把我的1个LP token交还给Uniswap时,我有权利从pool拿走它按比例对应的手续费。假设此时整个资金池共发出了X个LP token,我的流动性贡献占比就是1/X,我就可以获得A/X个ETH和B/X个DAI,然后再赎回我的1ETH和400DAI。Uniswap通过AMM模式和为流动性提供者奖励手续费的模式,极大地调动了LP的积极性。由于任何人都可以提供流动性并且从中获利,人们有动力为Uniswap提供流动性;交易所获得充足的交易流动性,交易滑点就小,用户体验也好。交易所的运行完全基于市场的需求进行。人工的运维成本大幅降低。在Uniswap中,交易产品的挂牌会是免费的。而且由于不需要再用交易订单的模式,而且流动性也不需要专门的做市商来提供,因此目前证券市场中的做市商的成本就可以取消。降低了上币成本和做市成本,Uniswap对DeFi和整个区块链行业的发展起到了一定的促进作用。为Uniswap提供流动性的用户可以获得经济激励。不过,这种激励存在两个美中不足之处:1)对早期参与流动性提供的用户不够公平。Uniswap能够运转,全凭流动性提供者为它提供了大量的流动性。早期流动性提供者承担了更多的风险,但并没有因此获得更多的收益。Uniswap依靠着早期的LP存入的资金逐步发展,随着它越来越受欢迎,有越来越多的像风投基金、交易所、矿池这样的大资金进入提供流动性。虽然交易手续费累计的很多,但是早期LP的份额被摊薄了,他们没有能够享受到协议成长带来的长期回报。这有点像早期的滴滴司机或者淘宝店主,正是他们让平台实现了发展,然而在平台发展之后他们并没有享受到更多的收益。此外,流动性提供者只有在他们提供流动性时才赚取资金池的交易费。一旦他们撤回资金池中自己的资金,将不再获得相应的收入。2)无常损失得不到补偿。为Uniswap提供流动性可以交易手续费,但也存在无常损失。无偿损失是指流动性提供者按当时的市价存入2种代币,在他要取出这些代币时,它们的兑换价格发生了变化而导致的损失。如果这2种代币中某个代币大幅上涨或下跌都可能导致无常损失。注意,不管涨还是跌,都有可能导致损失。还是以上面表格里的X和Y为例。当10个X换1个Y时,我存入100X和10Y。假设现在行情变化,也就是X和Y的兑换比例变化了:不管现在是10个X换2个Y(Y跌了),还是20个X换1个Y(Y涨了),我如果想赎回我的资金,都必须按照现在的兑换比例,取出价格相等的X和Y,不能破坏资金池中2种代币的比例平衡,不然套利者就又要出动了。这也就是说,我取出来的不是我存入的100X和10Y,而是按照新的市价的兑换比例,比如120X和8Y。而这相比我直接持有100X和10Y不动,是会产生损失的。当然,它本质上也是资产的再平衡,从这个角度看,不算是无常损失。不过,在退出时,如果按照法币计价,可能会出现获得的费用收益不如直接持有代币所得的收益更高的现象。而且这个无常损失,是无偿的损失。Sushiswap的经济激励机制Sushiswap在Uniswap的激励机制基础上做出了一些改变,这是它们二者最大的区别。Sushiswap增加了代币经济激励,也就是将其交易费用的一部分分配给Sushiswap代币SUSHI的持有人。Uniswap没有发行平台币,它每笔交易收0.3%的手续费,再通过LP token的形式把交易费按比例分配给LP(流动性提供者)。Sushiswap发行了平台币SUSHI,它的交易手续费也是0.3%。它将这0.3%的手续费分成2个部分,其中0.25%提供给LP,方法和Uniswap一样;剩下的0.05%将用于回购SUSHI代币,即用这部分钱购买SUSHI代币持有者手里的SUSHI代币。这意味着,SUSHI的价值与Sushiswap平台交易量是挂钩的。在Sushiswap上,交易量越大,SUSHI捕获的价值就越高。SUSHI代币和COMP、LEND、YFI一样,也可以在二级市场交易。此外,为了保证研发和运营的持续,有10%SUSHI代币会用于开发和未来的迭代、审计等。Sushiswap的经济激励机制在Uniswap的基础上做了改进,它保证了早期参与者的长期利益。Sushiswap每个区块将释放100枚SUSHI代币,会均分给所有支持的代币池,LP们还是根据流动性贡献来按比例获得SUSHI。和Uniswap用LP token的形式来分配手续费不同,LP token只有在存入代币对时才发给用户,而SUSHI是每个区块都产生一次,根据用户现在的资金比例分配。这样即使未来有大资金进入Sushiswap,早期参与者的资金份额被摊薄,但是他们之前已经获得的SUSHI代币不会减少,这就相当于是挖到了“头矿”。更何况在最初的100,000个区块,SUSHI产量更高,每个区块释放1,000枚SUSHI。在Sushiswap交易额增长起来后,SUSHI代币的价格也水涨船高,早期参与者凭借着早期相对较高资金份额占比而积累下的SUSHI代币可以享受到Sushiswap长期发展带来的福利。此外,前文提及,Uniswap的LP在赎回了当初存入的代币对之后,就不能再获得交易所的手续费分成了,而Sushiswap的LP即使赎回了资金,也还能够凭借着持有的SUSHI代币获得币价上涨带来的利益。Sushiswap的经济激励机制也并非尽善尽美。SUSHI代币有2个主要用途。第1点是用于投票。投票决定每个区块产生的100个SUSHI在各个代币对兑换池中分配的比例,也就是哪个池子分到的SUSHI奖励多一点;投票决定是不是要新开放某个新代币对兑换池。对于特定的LP来说,这2种投票的目的都是为了让自己获得更多的SUSHI奖励,消耗一部分SUSHI以获得更多的SUSHI。这样会不会造成分配权重大的资金池分配比例越来越大呢,还有待时间的检验。第2点就是上文说的用于兑换那0.05%的手续费。在交易所蒸蒸日上的阶段这当然是好的了,不过如果交易额下降呢。无限通货膨胀的SUSHI和正在下降的手续费分成相互作用,会导致新产生的SUSHI越来越不值钱,对币价下降的预期则会让老持币人竞相抛售。如果他们再从流动性资金池里撤资,交易所流动性不足,引起交易滑点过大,用户体验变差,交易额就会进一步下降。这样的恶性循环会迅速让它承受巨大损失。这样的情形不一定会出现,但是会有这样的风险。虽然在Uniswap中同样存在交易额下降引发流动性下降的恶性循环,不过它没有平台币,也就没有币价下降的第三重刺激。Sushiswap中同样存在无常损失。Sushiswap的大招仅靠改进的经济激励模型,能不能让Sushiswap超越老大哥,坐上DEX头把交椅呢,我们不得而知。不过项目方还想了别的办法,真正的大招还在后头呢。第一步。Sushiswap为Uniswap的流动性提供者提供了赚取SUSHI代币的机会。Uniswap的流动性提供者可以将其LP token质押在Sushiswap,然后在区块高度10750000开始赚取SUSHI代币。目前只收LP token,还不能直接存入代币对。这好比是你在一家大银行Uniswap存了钱,它发给你一个收据,凭此取钱。新银行Sushiswap说,你的收据质押在我这里,1星期以后我给你这张收据发利息,你的钱还在原来的银行,收据你想拿走随时拿走。这样的好事谁不干,于是大家纷纷把Uniswap的LP token质押在Sushiswap。只要LP token第二步。在协议启动大约两周(最初100,000个区块)后,Sushiswap会启动针对Uniswap的流动性池迁移计划。在迁移过程中,首先是这一批用户在Uniswap上进行代币对的赎回,然后将这些代币池迁移,也就是把从Uniswap里取出来的钱存到Sushiswap里。就这样,Sushiswap将获得大量的流动性,它的流动性是从Uniswap那里直接拿来的。近日Uniswap锁仓量(就是资金池的存款量)暴涨,原因就是Sushiswap只收Uniswap的LP token,用户必须先到Uniswap去存钱,换出LP token,才能把它质押到Sushiswap里。复制粘贴你的运行原理,剪切粘贴你的用户。SIGOI!(日语:好厉害)风险最后我们谈一谈这两家DEX的风险。l 技术风险Uniswap在2020年3月19日在以太坊主网上推出了一个新版本,还配合着公开了核心合约的1.0.1版;在发行之前,该版本已经在Rinkeby测试网上测试过一段时间了。这个新版本在以太坊主网上已经使用超过了两个月时间,而且迄今为止,没有出现任何损坏智能合约完整性的问题。Uniswap V2 在上线主网之前经过了充分的测试和审核。对源代码的尽职审核“很有可能”保证了未来不会发现任何重大的问题,不过Uniswap还是发布了一个Bug悬赏,任何人发现了重大漏洞都可以获得奖金。从Sushiswap宣布的信息看,它邀请Trail of Bits、PeckShield、OpenZeppelin、Consensys、Certik、Quantstamp中的其中一家对其合约进行审计。但目前为止还没有完成正式审计。这里是有潜在风险的。即便完成了审计,任何流动性挖矿都存在潜在的智能合约漏洞风险。编写出没有任何错误的代码是非常困难的,而开发人员也不可能设想到所有的潜在风险,尤其是在DeFi发展如此火爆的今天。Uniswap和Sushiswap都存在一定程度的技术风险。审计、测试以及购买智能合约保险都可以降低技术风险。l 经济模型风险许多区块链项目,特别是在DeFi领域,都需要依靠经济激励来激励网络的参与者。有时候经济模型看起来无懈可击,却包含着潜在的风险。对于这两家DEX的LP来说,首先要面对的就是上文所说无常损失风险。而且是为价格波动越大的币种提供流动性,出现无常损失的风险越高,这导致很多用户发现,为DEX提供流动性(也就是流动性挖矿)带来的收益还不如无常损失更多。SUSHI是每个区块产生100个,它与比特币、以太币等不一样。比特币只有2100万枚,而SUSHI是无限通货膨胀的,未来Sushiswap的交易额增长能够跑得过无限通胀呢,现在还没有一个明确的结论。交易额下降会不会引发流动性枯竭,造成恶性循环,这是它们都面临的风险。l 外部风险外部风险指的不是Uniswap和Sushiswap本身存在的风险,而是在它们上线的项目中存在的风险。例如:项目的虚假宣传、项目方大量抛售代币导致币价崩盘等等。只需要建立两个资金池,就可以无上币费、无审查、无成本地“三无上币”,大大降低了项目方发币割韭菜的难度和成本,这简直比2017年还疯狂。结语:以前说币圈一天,人间一年,现在是DeFi圈一天,币圈一年。这两家swap不是“swap party”的谢幕,还会有更多DEX和其他项目粉墨登场。希望各项目能够互相促进,共同为数字金融和区块链行业的发展助力。本文部分观点参考以下文章:有关Uniswap V2的一切:新功能与工作原理。www.8btc.com/article/641872火币观察:SUSHI飙涨行情耀眼,SushiSwap是否存在风险?www.jinse.com/news/blockchain/804917.html从Uniswap看未来的数字资产交易所。www.8btc.com/article/636431全维度深入解析:Uniswap的正面与背面。www.8btc.com/media/636300SushiSwap锁仓超10亿美元,赚钱效应成DeFi繁荣的最大推手。www.jinse.com/news/blockchain/805211.htmlSushiswap:Uniswap的进化?http://blog.csdn.net/lanhubiji/article/details/108289403作者:蒋梦初2020年9月4日编辑于 2020-09-08 21:50区块链(Blockchain)去中心化金融(DeFi)赞同 34020 条评论分享喜欢收藏申请转载文章被以下专栏收录链习生原创,区块链领域,通俗
去中心化交易所:Uniswap v2白皮书中文版 - 知乎
去中心化交易所:Uniswap v2白皮书中文版 - 知乎切换模式写文章登录/注册去中心化交易所:Uniswap v2白皮书中文版Yeefea原文:Uniswap v2 Core作者:Hayden Adams - hayden@uniswap.orgNoah Zinsmeister - noah@uniswap.orgDan Robinson - dan@paradigm.xyz2020年3月Uniswap v2 核心摘要这篇技术白皮书解释了Uniswap v2核心合约背后的设计决策。内容覆盖了合约的新特性,包括任意ERC20代币的交易对,强化的价格预言机制(price oracle),允许交易者先接收资产并使用,随后在转账中支付的快速互换(flash swaps)功能,在未来可以开启的协议手续费(protocol fee)为了减少受攻击面,重新设计了合约的架构。本白皮书描述了Uniswap v2核心合约的运行机制,包括储存流动性提供者资金的交易对合约,和用于实例化交易对合约的工厂合约。1 介绍Uniswap v1是一个以太坊区块链上的智能合约系统,基于常数乘积公式实现了自动流动性协议。每个Uniswap v1交易对在资金池里储存两种资产,并位这两种资产提供流动性,维持这两种资产的乘积不减少。交易者支付30bp(译者注:0.3%)的交易手续费给流动性提供者。合约是不能升级的。Uniswap v2基于同样的公式实现,添加了几个特性。最重要的一个是支持ERC20代币/ERC20代币交易对,而不像v1只支持ERC20代币/ETH交易对。除此以外,它也强化了价格预言,在每个区块开始处累积两个资产的相对价格。这允许其他以太坊合约计算两个资产在任意时间区间上的TWAP价格。最后,它启用了快速互换(flash swaps)功能,用户可以自由地接收资产并把他们用在链上的其他地方,只要在转账的最后支付(或返还)即可。虽然合约通常来说不可升级,但是有一个私钥能够更新一个变量,打开链上5bp的手续费,这个变量一开始是关闭的,可以在未来打开,打开之后流动性提供者在每笔交易上赚取25bp,而不是30bp。Uniswap v2修复了一些v1中的小问题,也在实现中重新设计了架构,减少了Uniswap的受攻击面,通过把逻辑最小化放在核心合约(core contract)中,这个核心合约维持了流动性提供者的资金,从而使系统变得更容易升级。这篇论文描述了核心合约(core contract)的运行机制,以及用来实例化核心合约的工厂合约(factory contract)。实际上使用Uniswap v2需要通过一个“路由”合约(router contract),计算交易/存款数额并转移资金到交易对合约(pair contract)。译者注:合约代码:https://github.com/Uniswap/uniswap-v2-coreUniswap v1 白皮书:https://hackmd.io/@HaydenAdams/HJ9jLsfTz#%F0%9F%A6%84-Uniswap-Whitepaper2 新特性2.1 ERC20交易对Uniswap v1使用ETH作为过渡货币(bridge currency),每个交易对都包含ETH。这使得路由更简单(ABC和XYZ之间的每笔交易都通过ETH/ABC交易对和ETH/XYZ交易对进行),并且减少了流动性的分散。但是,这个规则给流动性提供者增加了可观的成本。所有流动资金提供者都有ETH的敞口,并且由于其他资产相对于ETH的价格变化而遭受无常损失(impermanent loss)。当两个资产ABC和XYZ相关时(例如,如果它们都是锚定美元的稳定币),则在Uniswap交易对ABC/XYZ上的流动性提供者遭受的无常损失会比ABC/ETH或XYZ/ETH交易对少。使用ETH作为强制性过渡货币也会给交易者带来成本。交易者必须支付的费用是直接购买ABC/XYZ交易对的费用的两倍,因此他们遭受两次滑点。 Uniswap v2允许流动性提供商为任意两个ERC20创建对合约。任意ERC20之间的交易对数量的激增可能会使寻找交易特定货币对的最佳路径变得更加困难,但是路由可以在更高的层面上处理(在链下处理或通过链上路由器或聚合器)。2.2 价格预言(Price oracle)Uniswap提供的t时刻的边际价格(marginal price,不包括手续费)可以用资产a的储备除以资产b的储备来计算。p_t=\frac{r^{a}_{t}}{r^{b}_{t}}\tag{1} 如果这个价格偏离(超出手续费足够的数额),套利者会和Uniswap进行交易使价格回归正常,所以Uniswap提供的价格趋向于追踪资产在相关市场的价格。这意味着它可以被用作一个近似的价格预言。但是用Uniswap v1作为链上价格预言是不安全的,因为它非常容易被操纵。假设一个其他的合约用当前的ETH-DAI的价格交割某个衍生品,操纵价格的攻击者会从ETH-DAI交易对买入ETH,在衍生品上触发结算(引起失真的结算价),然后再把ETH卖给交易对,用真实价格反向交易。这甚至可以用一个原子的转账来完成,或者通过一个控制区块内交易(transaction)顺序的矿工。Uniswap v2改进了预言的功能,通过测算和记录每个区块第一笔交易之前的价格(也就是前一个区块最后的价格)。这个价格比一个区块内的价格更难被操纵。如果攻击者提交了一笔交易(transaction)尝试在区块末尾处操纵价格,其他的套利者可以提交另一个交易(transaction)立即进行反向交易。某个矿工(或有足够gas填满整个区块的攻击者)可以操纵区块末尾处的价格,除非他们可以挖出下一个区块,否则他们他们没有特殊的的套利优势。具体来说,Uniswap v2追踪每个和合约交互的区块开始处的价格的累加和,来累加价格。每个价格用距离上一个更新价格的区块的时间进行加权,根据区块时间戳。这意思是累加器的值在任意时间(更新后)的值等于合约历史上每秒的现货价格的和。a_t = \sum_{i=1}^{t}p_i \tag{2} 要计算从时间 t1到t2的时间加权平均价(译者注:TWAP价格),一个外部调用者可以检查t1和t2时间的累加器的值,将后值减去前值,再除以期间经过的秒数。(注意,合约本身并不记录历史累加值,调用者必须在时间段开始处调用合约来读取和储存这个值。)p_{t_1,t_2} = \frac{\sum\nolimits_{i=t_1}^{t2}p_i}{t_2-t_1}=\frac{\sum\nolimits_{i=1}^{t_2}p_i-\sum\nolimits_{i=1}^{t_1}p_i}{t_2-t_1}=\frac{a_{t_2}-a_{t_1}}{t_2-t_1} \tag{3} 预言的用户可以选择这个区间的起始和结束时间。选择更长的区间可以让攻击者操纵价格的成本更高,虽然这会导致价格变化滞后。一个复杂之处:我们应该用资产B来计算资产A的价格还是用资产A来计算资产B的价格?虽然用B计算的A的现货价格总是用A计算的B的现货价格的倒数,但是在某一时间段内用B计算的A的均价不等于用A计算的B的均价的倒数。举个例子,如果USD/ETH价格在区块1中是100,在区块2中是300,USD/ETH的均价是200 USD/ETH,但是ETH/USD的均价是1/150 ETH/USD(译者注:他们的均价不是倒数关系)。因为合约无法知道用户想要用哪个资产作为账户单位,所以Uniswap v2会同时追踪两个价格。另一个复杂之处:有没有可能某个人发送资产给交易对合约,用来改变它的余额和边际价格,但又不和它交互,因此不会触发价格更新。如果合约简单的检查它自己的余额然后更新预言,攻击者可以在某一个区块中第一次调用合约之前向合约发送资产,从而操纵价格。如果上一次交易的区块是X秒以前,合约会在累加之前错误地把新价格乘以X,即使没有用户用那个价格进行过交易。为了防止这个问题,核心合约在每次交互后缓存它的资金储备,用缓存的资金储备更新价格预言而不用当前资金储备。除了保护价格预言被操纵,这个改动也启用3.2节中描述的合约重新架构。2.2.1 精度Solidity没有一等的非整型数的数据结构的支持,Uniswap v2用简单的二进制定点数格式编码和控制价格。具体来说,某一时间的价格存储为UQ112.112格式,意思是在小数点的任意一边都有112位精度,无符号。这些数字的范围是 [0,2^{112}-1] ,精度是 \frac{1}{2^{112}} 。 选择UQ112.112格式是由于实用的原因,因为这些数可以被存在uint224中,在256位中剩余的32位空余。储备资金各自存在uint112中,剩余32位存储空间。这些空闲空间被用于之前描述的累加过程。具体来说,储备资金和时间戳存储在至少有一个交易的最近的区块中,mod 232(译者注:取余数)之后可以存进32位空间。另外,虽然任意时间的价格(UQ112.112数字)确保可以储存进224位中,但某段时间的累加值确保能存下。存储A/B和B/A累加价格空间尾部附加的32位用来存连续累加溢出的位。这样设计意味着价格预言只在每一个区块的第一次交易中增加了3次SSTORE操作(目前花费15000gas)。主要的缺点是32位不足以储存时间戳并确保不溢出。事实上32位Unix时间戳的溢出日期是2106年7月2日。为了确保系统在这个日期后以及每 2^{32}-1 秒的间隔能够继续运行,预言简单要求每个间隔至少检查一次价格(大约136年一次)。这是由于累加的核心函数(mod取余运算)是溢出安全的,意思是预言用溢出算法计算差值,跨越溢出区间的交易可以被合理计算。2.3 快速互换(Flash Swaps)Uniswap v1中,用户用XYZ买ABC需要发送XYZ到合约,然后才能收到ABC。如果用户需要ABC为了获取他们支付的XYZ,这种方式不方便的。举个例子,用户可能在其他合约中用ABC买XYZ,为了对冲Uniswap上的价格,或者他们可能在Maker或Compound上卖出抵押品平仓然后返还给Uniswap。Uniswap v2添加了一个新的特性,允许用户在支付前接收和使用资产,只要他们在同一个原子的转账中完成支付。swap函数调用一个可选的用户指定的回调合约,在这之间转出用户请求的代币并且强制确保不变。一旦回调完成,合约检查新余额并且确保满足不变(在经过支付手续费调整后)。如果合约没有足够的资金,它会回滚整个交易。用户也可以用同样的代币返还给Uniswap资金池而不完成互换。这高效地让任何人从Uniswap资金池中快速借取任何资产(Uniswap收取同样的千分之三的交易手续费)。2.4 协议手续费(Protocol fee)Uniswap v2包括0.05%协议手续费,可以打开或关闭,如果打开,手续费会被发送给工厂合约中指定的feeTo地址。初始时,feeTo没有被设定,不收手续费。一个预先指定的地址feeToSetter可以在Uniswap v2工厂合约上调用setFeeTo函数,设置feeTo地址。feeToSetter也可以自己调用setFeeToSetter修改feeToSetter地址。如果feeTo地址被设置,协议会收取5pb的手续费,从流动性提供者的30bp手续费中抽取1/6。交易者将在所有交易上支付0.3%手续费,83.3%的手续费给流动性提供者,16.6手续费给feeTo地址。总共收集的手续费可以用自从上次手续费收集以来(译者注:k是常数乘积,可以看v1白皮书)的增长来计算(也就是 )。以下公式给出了t1和t2之间的累加手续费占t2时间资金池中流动性的百分比:f_{1,2} = 1 - \frac{\sqrt{k_1}}{\sqrt{k_2}} \tag{4} 如果fee在时间t1前启用,feeTo地址应该获得1/6的t1到t2时间段内的累加手续费。因此,我们要铸造新的流动性代币给feeTo地址 \phi \cdot f_{1,2} ,其中 \phi = \frac{1}{6} 。我们要选择一个sm满足以下关系,其中s1是t1时刻的流通份额(outstanding shares)总量:\frac{s_m}{s_m+s_1}=\phi \cdot f_{1,2} \tag{5} 经过变换,将替换为后,解得s_m=\frac{\sqrt{k_2}-\sqrt{k_1}}{(\frac{1}{\phi}-1)\cdot\sqrt{k_2}+\sqrt{k_1}} \cdot s_1 \tag{6} 设,得到以下公式s_m=\frac{\sqrt{k_2}-\sqrt{k_1}}{5\cdot\sqrt{k_2}+\sqrt{k_1}} \cdot s_1 \tag{7} 假设初始存款人存了100DAI和1ETH在交易对中,收到10份额。一段时间后(如果没有其他存款人参与)他们把钱转出,这时交易对有96DAI和1.5ETH,用上面得公式可以得出:s_m=\frac{\sqrt{1.5 \cdot 96}-\sqrt{1 \cdot 100}}{5\cdot\sqrt{1.5 \cdot 96}+\sqrt{1 \cdot 100}} \cdot 10 \approx 0.0286 \tag{8} 2.5 资金池份额的元交易(Meta transactions for pool shares)Uniswap v2交易对铸造得资金池份额原生支持元转账。这意思是用户可以用签名授权一个他们的资金池份额的转账,而不用从他们的地址进行链上转账。任何人都可以调用permit函数来以用户的名义发送签名,支付gas手续费并在同一个转账中执行其他操作。3 其他修改3.1 SolidityUniswap v1是用Vyper实现的,一种类似于Python的智能合约预言。Uniswap v2是用更广泛使用的Solidity实现的,因为它在开发的时候需要一些Vyper中不可用的功能(比如翻译非标准ERC20代币的返回值,通过内联汇编访问新的字节码chanid)。3.2 合约重新架构Uniswap v2在设计时优先考虑的一个方面是最小化受攻击表面积和核心交易对合约的复杂度,交易对合约储存了流动性提供者的资产。这个合约中的任何bug都可能是灾难性的,因为数百万美元的流动性可能会被窃取或冻结。在评估核心合约的安全性时,最重要的问题时它是否保护流动性提供者以防他们的资产被窃取或冻结。除了基本的允许资产在资金池中互换的功能,任何支持或保护交易者的特性,都可以在路由合约中处理。事实上,甚至一部分的互换功能也可以被抽出放到路由合约中。之前提到过,Uniswap v2储存有每种资产最近一次记录的余额(为了防止预言机制被操纵)。新的架构利用了这一点来进一步简化Uniswap v1合约。Uniswap v2中,卖方在调用互换函数之前发送资产到核心合约。然后合约通过比较上次记录的余额和最新余额来计算它收到了多少资产。这意味着核心合约对交易者转账的方式是不可知的。除了transferFrom以外,也可能是元交易(meta transaction),或未来任何其他的授权ERC20代币转账的机制。3.2.1 手续费调整Uniswap v1通过转入合约的代币数量,在保持常数乘积不变之前收取交易手续费。合约强制确保了以下公式:(x_{1} - 0.003 \cdot x_{in}) \cdot y_1 >= x_0 \cdot y_0 \tag{9} 使用flash swaps时,Uniswap v2引入了xin和yin可以同时为非零的可能性(当用户想要返还同样的资产,而不是互换时)。为了处理这种情况,同时正确地收取手续费,合约强制确保:( x_1 - 0.003 \cdot x_{in}) \cdot (y_1 - 0.003 \cdot y_{in}) >= x_0 \cdot y_0 \tag{10} 为了简化链上计算,两边同时乘以1000000,得到:(1000 \cdot x_1 - 3 \cdot x_{in}) \cdot (1000 \cdot y_1 - 3 \cdot y_{in}) >= 1000000 \cdot x_0 \cdot y_0 \tag{11} 3.2.2 sync()和skim()函数为了防止特殊实现用来修改交易对合约余额的代币,并且更优雅地处理总发行量超过的代币,Uniswap v2有两个救援函数:sync()和skim()。sync()作用是在代币异步地减少交易对的余额时的恢复机制。这种情况下,交易会收到次优的汇率,如果没有流动性提供者作出反应,交易对会卡住。sync()的作用是设置合约的储备金为合约当前的余额,提供一种稍微优雅一点的恢复机制。skim()作用是在发送到代币的数量溢出了uint112大小的储备金存储空间时的恢复机制,否则交易会失败。skim()函数允许用户将提出交易对当前余额和的差值大于0时,将差值提出到调用者的地址。3.3 处理非标准和非常规代币ERC20标准要求transfer()函数和transferFrom()函数返回布尔值表示调用的成功或失败。一些代币对这两个函数的实现没有返回值,比如泰达币(USDT)和币安币(BNB)。Uniswap v1将这种不标准的函数返回值转换成false,表示转账不成功,并且回滚交易,导致转账失败。Uniswap v2用不同的方式处理非标准的代币实现。具体来说,如果一次transfer()调用没有返回值,Uniswap v2把它转换为成功而非失败。这个改动不应该影响任何遵从ERC20协议的代币(因为那些代币中transfer()总是有返回值)。Uniswap v1此外假设调用transfer()和transferFrom()不能触发Uniswap交易对合约的重入调用。某些ERC20代币违反了这个假设,包括支持ERC777协议的"hooks"的代币。为了完全支持这些代币,Uniswap v2包含了一个“锁”,直接防止重入所有公共的修改状态的函数。这也保护防止了在快速互换(flash swaps)中从用户定义的回调函数重入,如2.3节所描述的那样。3.4 初始化流动性代币供给当新的流动性提供者向现有的Uniswap交易对中存代币时,计算铸造的流动性代币(译者注:流动性代币需要看Uniswap v1白皮书)数量基于现有的代币数量:s_{minted}=\frac{x_{deposited}}{x_{starting}} \cdot s_{starting} \tag{12} 如果是第一个存款人呢?在 x_{starting} 为0的情况下,这个公式不能用。Uniswap v1设初始份额供给等于存入地ETH数量(以Wei计)。这有一定的合理价值,因为如果初始流动性是在合理价格存入的,那么1流动性份额(和ETH一样是18位小数精度代币)大约值2ETH。但是这意味着流动性资金池份额的价值依赖于初始存入的比例,这完全可能是任意值,尤其是因为没有任何比例可以反应真实价格的保证。另外,Uniswap v2支持任意交易对,有许多交易对根本不包含ETH。相反,Uniswap v2初始铸造份额等于存入代币数量的几何平均值:s_{minted}=\sqrt{x_{deposited}\cdot y_{deposited}} \tag{13} 这个公式确保了流动性资金池份额的价值在任意时间和在本质上和初始存入的比例无关。举个例子,假设当前1 ABC的价格是100XYZ。如果初始存款是2 ABC和200 XYZ(比例1:100),存款人会获得份额。这些份额现在应该任然值2 ABC和200 XYZ,加上累加手续费。如果初始存款是2 ABC和800 XYZ(1:400比例),存款人会收到资金池份额。以上公式确保了流动性资金池不会少于资金池中储备金额的几何平均值。但是,流动性资金池份额的价值随时间增长是可能的,通过累加交易手续费或者向流动性资金池“捐款”。理论上,这会导致一种极端情况,最小的流动性份额数量(1e-18份额)过于值钱,以至于无法位小流动性提供者提供任何流动性。为了减轻这种情况,Uniswap v2销毁第一次铸造的1e-15资金池份额,发送到全零地址而不是铸造者。这对任何代币交易对都是微不足道的。但是这显著地提高了上述攻击地成本。为了提高流动性资金池份额价值到100美元,攻击者需要捐献100000美元到资金池总,这会被作为流动性永久锁定。3.5 包装ETH以太坊原生资产ETH的转账接口和ERC20交互用的标准接口不同。结果,以太坊上许多其他的协议不支持ETH,而是使用了一种标准的“包装的ETH”代币,WETH。Uniswap v1是一个例外。因为每个Uniswap v1交易对包含了ETH作为其中一种资产,所以它可以直接处理ETH,而且更高效地使用gas。因为Uniswap v2支持任意ERC20交易对,它现在不再支持无包装的ETH。如果添加这个特性需要两倍的核心代码,并且产生ETH和WETH流动性分散的风险。原生ETH需要包装后才能在Uniswap v2上交易。3.6 确定交易对地址和Uniswap v1一样,Uniswap v2交易对也是通过单一的工厂合约进行实例化的。在Uniswap v1中,交易对合约用CREATE运算码进行创建,这意味着合约地址依赖于交易对创建的顺序。Uniswap v2使用以太坊新的CREATE2运算码来创建确定地址的交易对合约,这意味着可以在链下计算某个交易对的地址,不用查看以太坊区块链的状态。3.7 最大代币余额为了高效地实现预言机制,Uniswap v2只支持最高储备余额 2^{112}-1 。这个数字足以支持总发行量超过一千万亿的18位小数精度的代币。如果储备余额超过了,任何swap函数调用都会失败(由于_update()函数中的检查逻辑)。要从这个状态中恢复,任何用户都可以调用skim()函数从流动性池中删除超出的资产。引用[1] Hayden Adams. 2018. url: https://hackmd.io/@477aQ9OrQTCbVR3fq1Qzxg/HJ9jLsfTz?type=view.[2] Guillermo Angeris et al. An analysis of Uniswap markets. 2019. arXiv: 1911.03380[q-fin.TR].[3] samczsun. Taking undercollateralized loans for fun and for profit. Sept. 2019. url:https://samczsun.com/taking-undercollateralized-loans-for-fun-and-for-profit/.[4] Fabian Vogelsteller and Vitalik Buterin. Nov. 2015. url: https://eips.ethereum.org/EIPS/eip-20.[5] Jordi Baylina Jacques Dafflon and Thomas Shababi. EIP 777: ERC777 Token Standard.Nov. 2017. url: https://eips.ethereum.org/EIPS/eip-777.[6] Radar. WTF is WETH? url: https://weth.io/.[7] Uniswap.info. Wrapped Ether (WETH). url: https://uniswap.info/token/0xc02aaa39b223fe8d0a0e5c4f27e[8] Vitalik Buterin. EIP 10144 声明这篇论文的目的仅作为一般信息。不构成买卖任何投资产品的投资建议或推荐或请求,也不应该被用来评估任何投资决策的业绩,不应该被用于会计、法律或税务建议或投资推荐。本文反映了作者当前的观点,不代表Paradigm和其附属机构,也不一定反映Paradigm、其附属机构以及隶属于Paradigm的个人的观点。本文反映的观点在没有另行更新的情况下可能发生变化。翻译不易,别忘了点赞收藏加关注哦^_^编辑于 2020-10-11 13:26区块链(Blockchain)区块链技术赞同 582 条评论分享喜欢收藏申请