SunSwap v3兑换简介

SunSwap V3兑换协议核心概念: 做市商原理、流动性池及兑换

背景

尽管SunSwap V2在去中心化交易领域取得了巨大成功,但它也存在一些局限性。其中一个主要问题是流动性的利用率低。SunSwap V3引入了集中资金利用率的概念,允许流动性提供者将资金集中在特定价格范围内。这意味着他们可以更有效地提供流动性,并在价格波动较大的区间内获得更高的收益。

为了解决这个问题,SUN.io团队开发了SunSwap V3。SunSwap V3于2023年6月推出,引入了一种新的交易模型,称为"集中流动性"。在SunSwap V3中,流动性提供者可以选择在特定价格范围内提供资金,而不是将资金固定在一个交易对中。这样可以提高流动性的效率,并为交易者提供更好的价格选择。SunSwap V3引入了动态手续费模型,使流动性提供者能够在不同价格范围内设置不同的手续费率。这样可以提高流动性提供者的收益,并激励他们提供更多的流动性。

原理简介

基于恒定乘积公式来推演兑换的逻辑, 以x和y代表两种代币(假设为X和Y)的数量,则:

xy=L\sqrt{xy} = L
p=y/x\sqrt{p} =\sqrt{y/x}

L 被称作流动性。池子中的流动性是两种 token 资产数量的组合。我们知道,按照公式,两种代币数量乘积为k,因此我们可以用xy\sqrt{xy} 来衡量池子流动性。L 实际上是x和y的几何平均数。

y/x是token0和token1的价格。由于池子里两种代币的价格互为倒数,我们在计算中仅使用其中一个(SunSwap V3使用的是y/x)。

同样的L也表示了输出数量的变化与p\sqrt{p} 的变化关系:

L=ΔyΔPL=\frac{\Delta y}{\Delta \sqrt{P}}

证明:

L=ΔyΔPL=\frac{\Delta y}{\Delta \sqrt{P}}
L=y1y0P1P0L=\frac{y_1-y_0}{ \sqrt{P_1}-\sqrt{P_0}}
(P1P0)xy=y1y0(\sqrt{P_1}-\sqrt{P_0})\sqrt{xy}= {y_1-y_0}{ }
(y1/x1y0/x0)xy=y1y0(\sqrt{y_1/x_1 }-\sqrt{ y_0/x_0})\sqrt{xy}= {y_1-y_0}{ }

因为xy=x0y0=x1y1\sqrt{xy} =\sqrt{x_0y_0} =\sqrt{x_1y_1} ,故:

(y12y02)=y1y0(\sqrt{y_1^2 }-\sqrt{ y_0^2})= {y_1-y_0}
y1y0=y1y0{y_1-y_0}={y_1-y_0}

合约地址

Factory

主网合约地址: TThJt8zaJzJMhCEScH7zWKnp5buVZqys9x

nile测试网合约地址:TUTGcsGDRScK1gsDPMELV2QZxeESWb1Gac

SwapRouter

主网合约地址: TQAvWQpT9H916GckwWDJNhYZvQMkuRL7PN

nile测试网合约地址:TFkswj6rUfK3cQtFGzungCkNXxD2UCpEVD

NonfungiblePositionManager

主网合约地址: TLSWrv7eC1AZCXkRjpqMZUmvgd99cj7pPF

nile测试网合约地址:TPQzqHbCzQfoVdAV6bLwGDos8Lk2UjXz2R

与合约交互

我们利用TronWeb与合约交互, 初始化TronWeb实例后, 就能很方便的与线上合约交互

初始化TronWeb实例
const TronWeb = require('tronweb')
const privateKey = process.env.PRIVATE_KEY
const apiKey = process.env.API_KEY

var tronWeb = new TronWeb({
	fullHost: "https://api.trongrid.io",
	headers: { "TRON-PRO-API-KEY": apiKey },
	privateKey: privateKey,
      })

查询信息

  • 获取流动性地址

    • 名称:getPool(address,address,uint24)

    • 调用合约:Factory

    • 参数:token0地址,token1地址,fee率

    • 返回值:pool的地址

>>> let contract = await tronWeb.getContract('TThJt8zaJzJMhCEScH7zWKnp5buVZqys9x')
>>> await contract.methods.getPool('TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',‘TPYmHEhy5n8TCEfYGqW2rPxsghSfzghPDn’,100).call()
0x839538A1B5E9B57C639035A453E07C9A4309F9D9
  • 获取pool的信息

    • 名称:slot0()

    • 调用合约:pool合约(通过factory可以获得该合约地址)

    • 参数:无

    • 返回值: 1、当前价格(获取的价格进行平方除以2的192次方获得当前价格);2、当前所在tick;3、观测值数组的最新更新索引;4、当前存储的观测值的最大数量;5、在观察中触发的下一个要存储的最大观测值数;6、当前协议费占提款时掉期费的百分比;7、池子是否已锁定

>>> let contract = await tronWeb.getContract('TSUUVjysXV8YqHytSNjfkNXnnB49QDvZpx')
>>> await contract.methods.slot0().call()
[
  sqrtPriceX96: BigNumber { _hex: '0x4714a6b4d8e3d1ab6bcfbe0c', _isBigNumber: true },
  tick: -25629,
  observationIndex: 0,
  observationCardinality: 1,
  observationCardinalityNext: 1,
  feeProtocol: 0,
  unlocked: true
]
  • 获取用户tokenId

    • 名称:tokenOfOwnerByIndex(address,uint256)

    • 调用合约:NonfungiblePositionManager

    • 参数:用户地址,用户的第n个流动性证明

    • 返回值: tokenId

>>> let contract = await tronWeb.getContract('TLSWrv7eC1AZCXkRjpqMZUmvgd99cj7pPF')
>>> await contract.methods.tokenOfOwnerByIndex('TF5MekHgFz6neU7zTpX4h2tha5miPDUj3z',0).call()
1
  • 获取用户流动性

    • 名称:positions(uint256)

    • 调用合约:NonfungiblePositionManager

    • 参数:tokenId

    • 返回值: 1、nonce;2、tokenId授权地址;3、池子中token0地址;4、池子中token1地址;5、池子fee率;6、选择的position的最低值;7、选择的position最高值;8、流动性;9、10、截至对单个头寸的最后一次操作时总头寸的费用增长;11、12、截至上次计算,该头寸欠多少未收集的代币

>>> let contract = await tronWeb.getContract('TLSWrv7eC1AZCXkRjpqMZUmvgd99cj7pPF')
>>> await contract.methods.positions (1).call()
[
  nonce: 0
  operator: T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb
  token0: TF9io9LGyjuK3uTpr73pAaQ5m9scxd9xvr
  token1: TK8E3sFhBt3EB6gTT6d6co8RMB6DFUnNwE
  fee: 3000
  tickLower: -283380
  tickUpper: -269520
  liquidity: 1390641886550414128
  feeGrowthInside0LastX128: 0
  feeGrowthInside1LastX128: 540564213145032425660083902
  tokensOwed0: 0
  tokensOwed1: 0
]

执行交易

  • 交易

    • 名称:exactInput(ExactInputParams)

    • 调用合约:SwapRouter

    • 参数:[path的encode,用户地址,deadline]

>>> let contract = await tronWeb.getContract('TQAvWQpT9H916GckwWDJNhYZvQMkuRL7PN')
>>> await contract.methods.exactInput(['0xe518c608a37e2a262050e10be0c9d03c7a0877f3000bb843c42f702b0a11565c46e34022aab677d7bd8ae3','TF5MekHgFz6neU7zTpX4h2tha5miPDUj3z',1662825600])
  • 添加流动性

    • 名称:increaseLiquidity(IncreaseLiquidityParams)

    • 调用合约:NonfungiblePositionManager

    • 参数:[tokenId,token0添加的数量,token1添加数量,token0最小添加量,token1最小添加量,deadline]

>>> let contract = await tronWeb.getContract('TLSWrv7eC1AZCXkRjpqMZUmvgd99cj7pPF')
>>> await contract.methods.increaseLiquidity(1,'1000000000000000000','1000000000000000000',1,1,1662825600)
  • 降低流动性

    • 名称:decreaseLiquidity(DecreaseLiquidityParams)

    • 调用合约:NonfungiblePositionManager

    • 参数:[tokenId,需要移除的流动性,获得最小token0数量,获得最小token1数量,deadline]

>>> let contract = await tronWeb.getContract('TLSWrv7eC1AZCXkRjpqMZUmvgd99cj7pPF')
>>> await contract.methods.decreaseLiquidity(1,'1390641886550414128',1,1,1662825600)
  • 获取奖励

    • 名称:collect(CollectParams)

    • 调用合约:NonfungiblePositionManager

    • 参数:[tokenId,接受奖励地址,获得token0的最大奖励,获得token1的最大奖励]

>>> let contract = await tronWeb.getContract('TLSWrv7eC1AZCXkRjpqMZUmvgd99cj7pPF')
>>> await contract.methods.collect(1,'TF5MekHgFz6neU7zTpX4h2tha5miPDUj3z',‘100000000000000000000000000’,‘100000000000000000000000000’)

Last updated