[关闭]
@zoand 2023-08-01 09:41 字数 6163 阅读 421

调用合约进行Swap交易(以SCGT为例)

platon


合约地址

合约名称 测试环境(PLATON Testnet) 生产环境(PLATON Mainnet)
DipoleFactory 0x0b428E9f0CAC5A1D04609F5a6D3d5205F1eA152F 0x74Dd7b2dC60070516f26AcC30a5C734D3c87B2c9
DipoleRouter 0x38EC1D8267b9A26b73716395618FE9ae777656d3 0x78b674FBC75c43c3D91A35fFFA938268040C1990
WLAT 0xCC9fBAB49C29B3FF536A3d94873e988cC4A572aF 0x02406D561069cBed27eF8Ea20AFD41779A90e2Bf
合约名称 生产环境 测试环境
DipoleFactory 0x74Dd7b2dC60070516f26AcC30a5C734D3c87B2c9
DipoleRouter 0x78b674FBC75c43c3D91A35fFFA938268040C1990
CombinedSwapAddRemoveLiquidity 0x4041C496f0Dcf2aDCBb74bDF98667ce4895b361e
Multicall 0x74581a687cdfF1C3A64a4C66063AcD9f404B2D18
SmartChefFactory 0x0eb5a41AC2d6790335022a90656df5E364d0233F
initHash 0x8703d5f89be31a934ef8defce2c3d63a8f2a1217066ba898b6a34481a55527a0

Swap接口

授权

当输入代币为SCGT时,需要调用SCGT合约的approve方法,向DipoleRouter合约授权一定数量的SCGT,使DipoleRouter合约有权限从钱包地址中转出SCGT进行后续操作

参数名 类型 备注
spender address DipoleRouter合约地址
value uint 授权数量

swap

输入指定数量LAT,输出SCGT(swapExactETHForTokens)

参数名 类型 备注
amountOutMin uint 最小输出代币数量
path address[] 兑换路径上token地址的数组,[wlat地址,scgt地址]
to address 接收地址
deadline uint 交易超时时间戳(毫秒级)

输入LAT,输出指定数量SCGT(swapETHForExactTokens)

参数名 类型 备注
amountOut uint 指定输出代币数量
path address[] 兑换路径上token地址的数组,[wlat地址,scgt地址]
to address 接收地址
deadline uint 交易超时时间戳(毫秒级)

输入指定数量SCGT,输出LAT(swapExactTokensForETH)

参数名 类型 备注
amountIn uint 指定输入代币数量
amountOutMin uint 最小输出ETH数量
path address[] 兑换路径上token地址的数组,[scgt地址,wlat地址]
to address 接收地址
deadline uint 交易超时时间戳(毫秒级)

输入SCGT,输出指定数量LAT(swapTokensForExactETH)

参数名 类型 备注
amountOut uint 指定输出ETH数量
amountInMax uint 最大所需SCGT数量
path address[] 兑换路径上token地址的数组,[scgt地址,wlat地址]
to address 接收地址
deadline uint 交易超时时间戳(毫秒级)

预估兑换数量接口

计算原理

假设交易前交易对中LATSCGT的数量分别为ab,手续费为0.0025x不考虑多跳

接口

需要注意一下,DipolePair合约中有两对属性,token0/token1和reserve0/reserve1分别表示两个token地址和对应的reserve,并且token0和reserve0 、 token1和reserve1是一一对应的。

token0和token1是根据两个token地址对应的十六进制的大小确定的,token0 < token1

获取交易对地址

通过调用DipoleFactory合约的getPair方法获取

这里两个token address参数没有顺序要求

参数名 类型 备注
token0Address address WLAT地址
token1Address address SCGT地址

返回值:address类型的pair合约地址

获取Pair中两个token的Reserves

通过调用DipolePair合约的getReserves方法获取(无参数)

返回值

_reserve0 对应token0的reserve,_reserve1对应token1的reserve

属性名 类型 备注
_reserve0 uint token0的reserve
_reserve1 uint token1的reserve

指定输入计算输出数量

通过调用DipoleRouter合约的getAmountOut接口获取

上一步得到的reserves需要判断一下哪个是wlat,哪个是scgt

参数名 类型 备注
amountIn uint 输入token数量
reserveIn uint 输入token reserve,此处为交易对中WLAT的reserve
reserveOut uint 输出token reserve,此处为交易对中SCGT的reserve

指定输出计算输入数量

通过调用DipoleRouter合约的getAmountIn接口获取

上一步得到的reserves需要判断一下哪个是wlat,哪个是scgt

参数名 类型 备注
amountOut uint 输出token数量
reserveIn uint 输入token reserve,此处为交易对中WLAT的reserve
reserveOut uint 输出token reserve,此处为交易对中SCGT的reserve

Swap 价格影响计算逻辑

假设交易前输入代币t和输出代币的数量分别为ab,手续费为0.0025x不考虑多跳

调用示例

以指定输入为例,指定输出同理

数据准备

  1. const routerAddr = '0x714377e2443aAaF9e1Fcdf77358639c9E01f68E6'
  2. const factoryAddr = '0xF386b1DCc39cC40aa8f22c03FD6929F17021f6eE'
  3. const wlatAddr = '0xa0C63FAC4e5425F4721FF3258c3FA5B381152F73'
  4. const scgtAddr = '0x01cE844128ECa5e94fA9763f829f5A8ed8D3C956'
  5. const amount = '1000000000000000000' // 1个(decimals为18)
  6. const deadline = '1652976000000'
  7. const to = '0x324b790ABbC496fFba372d7FBe6FA6eE68c5c675'
  8. const router = await DipoleRouter.at(routerAddr)
  9. const factory = await DipoleFactory.at(factoryAddr)
  10. const scgt = await MockBEP20.at(scgtAddr)

预估兑换数量

以输入LAT输出SCGT为例,反向同理

  1. async function getAmountOut() {
  2. // 获取交易对地址
  3. const pairAddress = await factory.getPair(wlatAddr, scgtAddr)
  4. const pair = await DipolePair.at(pairAddress)
  5. // 获取reserves
  6. const { _reserve0, _reserve1 } = await pair.getReserves()
  7. // 根据token地址排序确定哪个是wlat,哪个是scgt
  8. const [ wlatReserve, scgtReserve ] =
  9. web3.utils.toBN(wlatAddr).lt(scgtAddr)
  10. ? [ _reserve0, _reserve1 ]
  11. : [ _reserve1, _reserve0 ]
  12. console.log('wlat reserve:', web3.utils.fromWei(wlatReserve).toString())
  13. console.log('scgt reserve:', web3.utils.fromWei(scgtReserve).toString())
  14. // 获取输出token数量
  15. const outputAmount = await router.getAmountOut(amount, wlatReserve, scgtReserve)
  16. console.log('output', web3.utils.fromWei(outputAmount).toString())
  17. }

输出

  1. wlat reserve: 200
  2. scgt reserve: 1500
  3. output 7.444122439333822559

1个LATSCGT

  1. async function swaExactLATForSCGT() {
  2. const params = [
  3. 0,
  4. [ wlatAddr, scgtAddr ],
  5. to,
  6. deadline
  7. ]
  8. // 估算调用swapExactETHForTokens接口所需gas
  9. const gas = await router.swapExactETHForTokens.estimateGas(...params, { value: amount })
  10. console.log('gas:', gas)
  11. params.push({
  12. value: amount,
  13. gas,
  14. gasPrice: '100000000000'
  15. })
  16. // 执行交易
  17. const result = await router.swapExactETHForTokens(...params)
  18. console.log(result)
  19. }

1个SCGTLAT

输入token不是LAT时,需要先对输入token进行授权

  1. async function swapExactSCGTForLAT() {
  2. const params = [
  3. amount,
  4. 0,
  5. [ scgtAddr, wlatAddr ],
  6. to,
  7. deadline
  8. ]
  9. // 授权
  10. await scgt.approve(router.address, amount)
  11. // 估算调用swapExactTokensForETH接口所需gas
  12. const gas = await router.swapExactTokensForETH.estimateGas(...params)
  13. console.log('gas:', gas)
  14. params.push({
  15. gas,
  16. gasPrice: '100000000000'
  17. })
  18. // 执行交易
  19. const result = await router.swapExactTokensForETH(...params)
  20. console.log(result)
  21. }

输出

  1. gas: 147653
  2. {
  3. tx: '0x2631b267686f501a38b8a45e20c7eb5e7f7477fa727dcd1ea30053bd0755e5a7',
  4. receipt: {
  5. blockHash: '0xd2f64dfc5e553a76c8ae724074b45d80ab896727c878254d4169d5d0c3c8ade3',
  6. blockNumber: 19997437,
  7. contractAddress: null,
  8. cumulativeGasUsed: 107389,
  9. from: '0x324b790ABbC496fFba372d7FBe6FA6eE68c5c675',
  10. gasUsed: 107389,
  11. logs: [],
  12. logsBloom: '0x00200000000000000000000080080000000000000000000000080000400800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000008000010200000000100400000000000000000000040000000000000000000000000000000000000000000040000000010000000000000000000000000000020000000000000000000000000080000004000000000020000000000000000000000000000000000200200000000000000000000000000000002000000000000000000000000000000200000001020000002000000001030000200000000000000000000000040000040000000800000000000000000',
  13. status: true,
  14. to: '0x4378dAF745E9053f6048c4f78c803f3bC8829703',
  15. transactionHash: '0x2631b267686f501a38b8a45e20c7eb5e7f7477fa727dcd1ea30053bd0755e5a7',
  16. transactionIndex: 0,
  17. rawLogs: [ [Object], [Object], [Object], [Object], [Object], [Object] ]
  18. },
  19. logs: []
  20. }

其他注意事项

  1. 为防止用户资金损失,根据滑点计算最小输出/最大输入,替换示例代码中swap方法参数里的0
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注