There are two methods available for initiating a swap, each with its own distinct advantages. The first method involves direct interaction with the Pair contract, while the second utilizes the Router contract. The primary distinction lies in the fact that the second method can facilitate the swapping of ETH, wherein the Router converts ETH to WETH before executing the actual swap. This section will provide guidance on both options.
1. Direct Swap within Pair Contract
Within the Pair contract, you'll encounter the following two functions. You have the flexibility to select the token for swapping, be it token0 or token1, and proceed with the swap.
minOutput : Minimum amount of token expected to receive.
Return Value:
output : Amount of token swapped.
Set Up your Contract
Declare the solidity version used to compile the contract.
Import the pair interface and IERC20 interface.
Write your own contract, here we name it MySwapTest. Remember that the caller must approve the contract to withdraw the tokens from the calling address's account to execute a swap.
// SPDX-License-Identifier: UNLICENSEDpragmasolidity 0.8.17;interface IPair {functionswap0in(address to,uint input,uint minOutput) externalreturns (uint output);functionswap1in(address to,uint input,uint minOutput) externalreturns (uint output);}interface IERC20 {functionapprove(address spender,uint value) externalreturns (bool);functiontransferFrom(address from,address to,uint value) externalreturns (bool);}contract MySwapTest {// The DYSON-USDC pair contract on Polygon zkEVM. // In this pair, the token0 represents $DYSN and token1 represents $USDC.address dysonUsdcPair =0xC9001AFF3701e19C29E996D48e474Baf4C5eD006;// The $DYSN contract on Polygon zkEVM.addresspublicconstant DYSN =0x9CBD81b43ba263ca894178366Cfb89A246D1159C;// The $USDC contract on Polygon zkEVM.addresspublicconstant USDC =0xA8CE8aee21bC2A48a5EF670afCc9274C7bbbC035;address to =address(this);// assume that 1 $DYSN = 1 $USDCuint dysonIn =100e18; // 100 $DYSNuint minUSDCOut =90e6; // Slippage = 10%uint usdcIn =100e6; // 100 $USDCuint minDysonOut =90e18// Slippage = 10%// Make sure caller wallet has enough $DYSNfunctionswapDYSNIn() externalreturns (uint output) {IERC20(DYSN).transferFrom(msg.sender,address(this), dysonIn)IERC20(DYSN).approve(dysonUsdcPair, dysonIn);returnIPair(dysonUsdcPair).swap0in(to, dysonIn, minUSDCOut); }// Make sure caller wallet has enough $USDCfunctionswapUSDCIn() externalreturns (uint output) {IERC20(USDC).transferFrom(msg.sender,address(this), usdcIn)IERC20(USDC).approve(dysonUsdcPair, usdcIn);returnIPair(dysonUsdcPair).swap1in(to, usdcIn,90e18); }}
Token0 and Token1, which is which?
The table presented below outlines the corresponding relationship. Specifically, concerning the Polygon zkEVM, token0 represents $DYSN, and token1 represents $USDC within the DYSON-USDC pair. The order is determined based on the address size, as follows:
Declare the solidity version used to compile the contract.
Import IRouter interface and IERC20 interface.
Create your custom contract. The following code snippets showcase the process of swapping between $DYSN and $USDC, as well as between $WETH and $USDC.
// SPDX-License-Identifier: UNLICENSEDpragmasolidity 0.8.17;interface IRouter {functionswap(address tokenIn,address tokenOut,uint index,address to,uint input,uint minOutput) externalreturns (uint output);functionswapETHIn(address tokenOut,uint index,address to,uint minOutput) externalpayablereturns (uint output);functionswapETHOut(address tokenIn,uint index,address to,uint input,uint minOutput) externalreturns (uint output); }interface IERC20 {functionapprove(address spender,uint value) externalreturns (bool);functiontransferFrom(address from,address to,uint value) externalreturns (bool);}contract MySwapTest {// The Router contract on Polygon zkEVM.addresspublicconstant router =0xADa6e69781399990d42bEcB1a9427955FFA73Bdc;// The $DYSN contract on Polygon zkEVM.addresspublicconstant DYSN =0x9CBD81b43ba263ca894178366Cfb89A246D1159C;// The $USDC contract on Polygon zkEVM.addresspublicconstant USDC =0xA8CE8aee21bC2A48a5EF670afCc9274C7bbbC035;functionswapDYSNToUSDC(uint index,address to,uint amountIn,uint minOutput) externalreturns (uint output) {IERC20(DYSN).transferFrom(msg.sender,address(this), amountIn)IERC20(DYSN).approve(router, amountIn);IRouter(router).swap(DYSN, USDC, index, to, amountIn, minOutput); }functionswapUSDCToDYSN(uint index,address to,uint amountIn,uint minOutput) externalreturns (uint output) {IERC20(USDC).transferFrom(msg.sender,address(this), amountIn)IERC20(USDC).approve(router, amountIn);IRouter(router).swap(USDC, DYSN, index, to, amountIn, minOutput); }// Ensure this contract has enough ETH before performing `swapETHToUSDC`.functionswapETHToUSDC(uint swapETHAmount,uint index,address to,uint minOutput) externalpayablereturns (uint output) {IRouter(router).swapETHIn{value: swapETHAmount}(USDC, index, to, minOutput); }// Ensure this contract has enough USDC before performing `swapUSDCToETH`.functionswapUSDCToETH(uint index,address to,uint input,uint minOutput) externalreturns (uint output) {IRouter(router).swapETHOut(USDC, index, to, input, minOutput); }}
swapWithMultiHops
In the context of Dyson Finance, assuming there are currently three pairs: token0-token1, token1-token2, and token2-token3. If a user intends to swap from token0 to token3, they should employ the following functions: swapWithMultiHops, swapETHInWithMultiHops, or swapETHOutWithMultiHops to achieve the desired outcome, as opposed to invoking a regular swap function.
Reiterating, our platform indeed facilitates the swapping of ETH in and out with multiple hops. The fundamental logic aligns with the original swapWithMultiHops function, with these specific functions aiding in the seamless conversion between ETH and WETH as required. In particular, swapETHInWithMultiHops transforms the user's input ETH to WETH before the actual swap, while swapETHOutWithMultiHops converts the output WETH back to ETH after swap and returns it to the user.
Declare the solidity version used to compile the contract.
Import IRouter interface.
Write your own contract. Let's consider a scenario where there are three pairs: token0-token1, token1-token2, and token2-token3, with each pair having an index of 1. Now, if a user aims to execute a swap from token0 to token3 using the swapWithMultiHops function, they need to provide an array that signifies the token paths: [token0, token1, token2, token3], along with the indices of each pair: [1, 1, 1].