@zoand
2023-08-01T09:41:13.000000Z
字数 6163
阅读 573
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 |
当输入代币为SCGT时,需要调用SCGT合约的approve方法,向DipoleRouter合约授权一定数量的SCGT,使DipoleRouter合约有权限从钱包地址中转出SCGT进行后续操作
| 参数名 | 类型 | 备注 |
|---|---|---|
| spender | address | DipoleRouter合约地址 |
| value | uint | 授权数量 |
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 | 交易超时时间戳(毫秒级) |
假设交易前交易对中LAT和SCGT的数量分别为a、b,手续费为0.0025x(不考虑多跳)
交易中输入代币和输出代币的数量分别为x和y,根据乘积恒定公式:
需要注意一下,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合约地址
通过调用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 |
假设交易前输入代币t和输出代币的数量分别为a、b,手续费为0.0025x(不考虑多跳)
交易中输入代币和输出代币的数量分别为x和y,根据乘积恒定公式:
lat对另一代币在交易前的市场价和预估的交易价格分别是
以指定输入为例,指定输出同理
const routerAddr = '0x714377e2443aAaF9e1Fcdf77358639c9E01f68E6'const factoryAddr = '0xF386b1DCc39cC40aa8f22c03FD6929F17021f6eE'const wlatAddr = '0xa0C63FAC4e5425F4721FF3258c3FA5B381152F73'const scgtAddr = '0x01cE844128ECa5e94fA9763f829f5A8ed8D3C956'const amount = '1000000000000000000' // 1个(decimals为18)const deadline = '1652976000000'const to = '0x324b790ABbC496fFba372d7FBe6FA6eE68c5c675'const router = await DipoleRouter.at(routerAddr)const factory = await DipoleFactory.at(factoryAddr)const scgt = await MockBEP20.at(scgtAddr)
以输入
LAT输出SCGT为例,反向同理
async function getAmountOut() {// 获取交易对地址const pairAddress = await factory.getPair(wlatAddr, scgtAddr)const pair = await DipolePair.at(pairAddress)// 获取reservesconst { _reserve0, _reserve1 } = await pair.getReserves()// 根据token地址排序确定哪个是wlat,哪个是scgtconst [ wlatReserve, scgtReserve ] =web3.utils.toBN(wlatAddr).lt(scgtAddr)? [ _reserve0, _reserve1 ]: [ _reserve1, _reserve0 ]console.log('wlat reserve:', web3.utils.fromWei(wlatReserve).toString())console.log('scgt reserve:', web3.utils.fromWei(scgtReserve).toString())// 获取输出token数量const outputAmount = await router.getAmountOut(amount, wlatReserve, scgtReserve)console.log('output', web3.utils.fromWei(outputAmount).toString())}
wlat reserve: 200scgt reserve: 1500output 7.444122439333822559
LAT转SCGT
async function swaExactLATForSCGT() {const params = [0,[ wlatAddr, scgtAddr ],to,deadline]// 估算调用swapExactETHForTokens接口所需gasconst gas = await router.swapExactETHForTokens.estimateGas(...params, { value: amount })console.log('gas:', gas)params.push({value: amount,gas,gasPrice: '100000000000'})// 执行交易const result = await router.swapExactETHForTokens(...params)console.log(result)}
SCGT转LAT输入token不是
LAT时,需要先对输入token进行授权
async function swapExactSCGTForLAT() {const params = [amount,0,[ scgtAddr, wlatAddr ],to,deadline]// 授权await scgt.approve(router.address, amount)// 估算调用swapExactTokensForETH接口所需gasconst gas = await router.swapExactTokensForETH.estimateGas(...params)console.log('gas:', gas)params.push({gas,gasPrice: '100000000000'})// 执行交易const result = await router.swapExactTokensForETH(...params)console.log(result)}
gas: 147653{tx: '0x2631b267686f501a38b8a45e20c7eb5e7f7477fa727dcd1ea30053bd0755e5a7',receipt: {blockHash: '0xd2f64dfc5e553a76c8ae724074b45d80ab896727c878254d4169d5d0c3c8ade3',blockNumber: 19997437,contractAddress: null,cumulativeGasUsed: 107389,from: '0x324b790ABbC496fFba372d7FBe6FA6eE68c5c675',gasUsed: 107389,logs: [],logsBloom: '0x00200000000000000000000080080000000000000000000000080000400800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000008000010200000000100400000000000000000000040000000000000000000000000000000000000000000040000000010000000000000000000000000000020000000000000000000000000080000004000000000020000000000000000000000000000000000200200000000000000000000000000000002000000000000000000000000000000200000001020000002000000001030000200000000000000000000000040000040000000800000000000000000',status: true,to: '0x4378dAF745E9053f6048c4f78c803f3bC8829703',transactionHash: '0x2631b267686f501a38b8a45e20c7eb5e7f7477fa727dcd1ea30053bd0755e5a7',transactionIndex: 0,rawLogs: [ [Object], [Object], [Object], [Object], [Object], [Object] ]},logs: []}