背景
SunSwap AMM(自动做市商)是目前DeFi领域应用最多的交易模型, 与订单簿的交易方式不 同,AMM采用的是固定乘积的方式换算兑换池内的代币,交易自动成交,并保证交易对的流动性不枯竭。
任何人都可以通过存入某种代币来换取等值的交易池代币,并成为这个交易池的流动性提供者(LP)。 这些代币数量除以交易池中LP总储备量代表流动性提供者的在该交易池中的资产占比,且流动性提供者可以随时赎回相关资产。
原理简介
基于恒定乘积公式来推演兑换的逻辑, 以x和y代表两种代币(假设为X和Y)的数量,则:
如果我们想用X从流动池中兑换Y,假设输入X的数量为Δx,兑换得到的Y的量为Δy,在交易池资金足够的前提下,则:
(x+Δx)×(y−Δy)=kΔy=y−x+Δxk=x+ΔxΔx×y 也就是说交易前后,流动性池中两种代币的乘积是恒定不变的,基于以上,如果交易的量相对于流动性池的量很小,那么交易价格就近似为两种代币的数量比:
pricey=ΔyΔx=yx+Δx≈yx 流动性池
SUN.io的Sunswap合约实现了普通代币兑换和流动性增删的功能, 能支撑多种代币之间的兑换,目前在TRON主网上主要部署了V1/V2两种版本的合约。
V1版本
Factory合约地址: TXk8rQSAvPvBBNtqSoY6nCfsXWCSSpTVQF
V2版本
Factory合约地址: TKWJdrQkqHisa1X8HUdHEfREvTzw4pMAaY
Router合约地址: TXF1xDbVGdxFGbovmmmXvBGu8ZiE3Lq4mR
注意:旧 Router 合约地址 TKzxdSv2FZKQrEqkKVgp5DcwEXBEKMg2Ax
已弃用。
与合约交互
我们利用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,
})
获取流动性信息
>>> let contract = await tronWeb.getContract('TXk8rQSAvPvBBNtqSoY6nCfsXWCSSpTVQF')
>>> await contract.methods.getExchange('TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t').call()
0x4cAD2750821493b093133B7bf10568bAEc000971
获取V2版本的流动性池地址
名称:getPair(address,address)
>>> let contract = await tronWeb.getContract('TKWJdrQkqHisa1X8HUdHEfREvTzw4pMAaY')
>>> await contract.methods.getPair('TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t', 'TNUC9Qb1rRpS5CbWLmNMxXBjyFoydXjWFR')
0x4cAD2750821493b093133B7bf10568bAEc000971
执行交易
V1版本卖出TRX买入Token
名称:trxToTokenTransferInput(uint256, uint256, address)
>>> let contract = await tronWeb.getContract('TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE')
>>> await contract.methods.trxToTokenTransferInput(100, 1662825600, 'TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE')
V1版本卖出Token买入TRX
名称:tokenToTrxTransferInput(uint256, uint256, uint256, address)
参数:出售币数量,预期购买TRX的最小额度,时间期限,收款地址
>>> let contract = await tronWeb.getContract('TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE')
>>> await contract.methods.tokenToTrxTransferInput(100, 1500, 1662825600, 'TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE')
V1版本卖出Token买入Token
名称:tokenToTokenSwapInput( uint256, uint256, uint256, uint256, address)
参数:出售币数量,预期购买币最小值,预期可购买token最小值,时间期限,收款地址
>>> let contract = await tronWeb.getContract('TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE')
>>> await contract.methods.tokenToTokenSwapInput(100, 100, 1500,1662825600,'TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE')
V2版本卖出Token买入Token
名称:swapExactTokensForTokens( uint, uint, address[], address, uint)
参数:出售币数量,预期购买币最小值,兑换路径,收款地址,时间期限
>>> let contract = await tronWeb.getContract('TKzxdSv2FZKQrEqkKVgp5DcwEXBEKMg2Ax')
>>> await contract.methods.swapExactTokensForTokens(1000000000000000000,1000000,['TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf','TF17BgPaZYbz8oxbjhriubPDsA7ArKoLX3'],'TF5MekHgFz6neU7zTpX4h2tha3mijDUj3z',1662825600)
V2版本卖出TRX买入Token
名称:swapExactETHForTokens(uint, address[], address, uint)
参数:预期购买币最小值,兑换路径,收款地址,时间期限
>>> let contract = await tronWeb.getContract('TKzxdSv2FZKQrEqkKVgp5DcwEXBEKMg2Ax')
>>> await contract.methods.swapExactETHForTokens(100000000,1,['TYsbWxNnyTgsZaTFaue9hqpxkU3Fkco94a','TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf'],'TF5MekHgFz6neU7zTpX4h2tha5miPDUj3z',1662825600)
V2版本卖出Token买入TRX
名称:swapExactTokensForETH(uint, uint, address[] , address, uint)
参数:出售币数量,预期购买TRX最小值,兑换路径,收款地址,时间期限
>>> let contract = await tronWeb.getContract('TKzxdSv2FZKQrEqkKVgp5DcwEXBEKMg2Ax')
>>> await contract.methods.swapExactTokensForETH(1000000,1000000,['TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf','TYsbWxNnyTgsZaTFaue9hqpxkU3Fkco94a'],'TF5MekHgFz6neU7zTpX4h2tha5miPDUj3z',1662825600)
增删流动性
V1版本增加流动性
名称:addLiquidity(uint256, uint256, uint256)
参数:预期获取最小流动性,要添加流动性的最大金额,时间期限
>>> let contract = await tronWeb.getContract('TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE')
>>> await contract.methods.addLiquidity(100, 100, 1662825600)
V1版本删除流动性
名称:removeLiquidity(uint256, uint256,uint256, uint256)
参数:移除流动性的数量,预期获取最小的TRX数量,预期获取最小token数量,时间期限
>>> let contract = await tronWeb.getContract('TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE')
>>> await contract.methods.removeLiquidity(100, 100, 100, 1662825600)
V2版本增加流动性
名称:addLiquidity(address,address,uint,uint,uint,uint,address,uint)
参数:tokenA地址,tokenB地址,tokenA预期添加的数量,tokenB预期添加的数量,tokenA添加的数量最小接受额,tokenB添加的数量最小接受额,添加流动性地址,时间期限
>>> let contract = await tronWeb.getContract('TKzxdSv2FZKQrEqkKVgp5DcwEXBEKMg2Ax')
>>> await contract.methods.addLiquidity('TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf','TF17BgPaZYbz8oxbjhriubPDsA7ArKoLX3',100000000,27661108481018349141,5000000,200000000000000000000,TF5MekHgFz6neU7zTpX4h2tha5miPDUj3z,1662825600)
V2版本删除流动性
名称:removeLiquidity(address,address,uint,uint,uint,address,uint)
参数:tokenA地址,tokenB地址,移除的流动性,预期获得tokenA数量的最小值,预期获得tokenB数量的最小值,token接收地址,时间期限
>>> let contract = await tronWeb.getContract('TKzxdSv2FZKQrEqkKVgp5DcwEXBEKMg2Ax')
>>> await contract.methods.removeLiquidity('TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf','TF17BgPaZYbz8oxbjhriubPDsA7ArKoLX3',100000000,1,1,TF5MekHgFz6neU7zTpX4h2tha5miPDUj3z,1962825600)