Uniswap V2与SushiSwap中getAmountsIn为何始终高于getAmountsOut?
为什么Uniswap V2/SushiSwap中getAmountsIn返回值高于getAmountsOut?
这是由Uniswap V2(以及fork它的SushiSwap)的恒定乘积做市商模型和交易手续费机制决定的,核心原因如下:
1. 两个函数的计算目标完全不同
getAmountsOut:给定你要输入的代币数量,计算扣除手续费后能拿到的目标代币数量。getAmountsIn:给定你想要拿到的目标代币数量,计算需要输入的代币数量(要覆盖手续费,保证最终能拿到目标量)。
2. 手续费的反向放大效应
Uniswap V2的交易手续费是0.3%,这个费用在两个函数的计算中影响方向不同:
- 调用
getAmountsOut(1 WETH, [WETH, USDC])时,输入的1 WETH会先扣除0.3%手续费(实际只有0.997 WETH进入流动性池子),再用恒定乘积公式x*y=k计算能兑换出的USDC数量。 - 调用
getAmountsIn(1 WETH, [USDC, WETH])时,为了确保最终能拿到1 WETH,需要先算出“无手续费情况下需要多少USDC才能换出1 WETH”,然后再除以0.997(因为手续费会从输入的USDC中扣除0.3%,所以必须多输入USDC才能让实际进入池子的金额足够支撑取出1 WETH)。
3. 恒定乘积模型的滑点叠加
即使忽略手续费,恒定乘积模型本身的滑点也会导致:用A换B得到的数量,再用这个数量的B换A,得到的A会少于最初的输入。再叠加手续费的损耗,就会让getAmountsIn的返回值(需要的输入)明显高于getAmountsOut的返回值(能拿到的输出)。
你的测试代码(格式化后)
from helper import * from decimal import Decimal wethAddr = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' usdcAddr = '0xdAC17F958D2ee523a2206206994597C13D831ec7' amount = uniRouter.functions.getAmountsOut(web3.to_wei(Decimal('1'), 'ether'), [wethAddr, usdcAddr]).call() amount2 = sushiRouter.functions.getAmountsOut(web3.to_wei(Decimal('1'), 'ether'), [wethAddr, usdcAddr]).call() amount3 = uniRouter.functions.getAmountsIn(web3.to_wei(Decimal('1'), 'ether'), [usdcAddr, wethAddr]).call() amount4 = sushiRouter.functions.getAmountsIn(web3.to_wei(Decimal('1'), 'ether'), [usdcAddr, wethAddr]).call() print(amount[1]) print(amount2[1]) print(amount3[0]) print(amount4[0])
内容的提问来源于stack exchange,提问作者Andrei Cosmin Marica
相关产品推荐
相关产品推荐

