mirror of
				https://github.com/Instadapp/dsa-connectors.git
				synced 2024-07-29 22:37:00 +00:00 
			
		
		
		
	Merge pull request #153 from Instadapp/uniswapv3-router
[mainnet] uniswap v3 auto router
This commit is contained in:
		
						commit
						af8ff0a769
					
				|  | @ -0,0 +1,12 @@ | |||
| pragma solidity ^0.7.0; | ||||
| 
 | ||||
| contract Events { | ||||
| 	event LogSwap( | ||||
| 		address indexed buyToken, | ||||
| 		address indexed sellToken, | ||||
| 		uint256 buyAmt, | ||||
| 		uint256 sellAmt, | ||||
| 		uint256 getId, | ||||
| 		uint256 setId | ||||
| 	); | ||||
| } | ||||
|  | @ -0,0 +1,80 @@ | |||
| pragma solidity ^0.7.0; | ||||
| 
 | ||||
| import { TokenInterface } from "../../../common/interfaces.sol"; | ||||
| import { DSMath } from "../../../common/math.sol"; | ||||
| import { Basic } from "../../../common/basic.sol"; | ||||
| import { SwapData } from "./interface.sol"; | ||||
| 
 | ||||
| abstract contract Helpers is DSMath, Basic { | ||||
| 	/** | ||||
| 	 * @dev UniswapV3 Swap Router Address | ||||
| 	 */ | ||||
| 	address internal constant V3_SWAP_ROUTER_ADDRESS = | ||||
| 		0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @dev UniswapV3 swapHelper | ||||
| 	 * @param swapData - Struct defined in interfaces.sol | ||||
| 	 */ | ||||
| 	function _swapHelper(SwapData memory swapData) | ||||
| 		internal | ||||
| 		returns (uint256 buyAmt) | ||||
| 	{ | ||||
| 		(uint256 _buyDec, uint256 _sellDec) = getTokensDec( | ||||
| 			swapData.buyToken, | ||||
| 			swapData.sellToken | ||||
| 		); | ||||
| 		uint256 _sellAmt18 = convertTo18(_sellDec, swapData._sellAmt); | ||||
| 		uint256 _slippageAmt = convert18ToDec( | ||||
| 			_buyDec, | ||||
| 			wmul(swapData.unitAmt, _sellAmt18) | ||||
| 		); | ||||
| 
 | ||||
| 		uint256 initalBal = getTokenBal(swapData.buyToken); | ||||
| 
 | ||||
| 		// solium-disable-next-line security/no-call-value | ||||
| 		(bool success, ) = V3_SWAP_ROUTER_ADDRESS.call(swapData.callData); | ||||
| 		if (!success) revert("uniswapV3-swap-failed"); | ||||
| 
 | ||||
| 		uint256 finalBal = getTokenBal(swapData.buyToken); | ||||
| 
 | ||||
| 		buyAmt = sub(finalBal, initalBal); | ||||
| 		require(_slippageAmt <= buyAmt, "Too much slippage"); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @dev Gets the swapping data from auto router sdk | ||||
| 	 * @param swapData Struct with multiple swap data defined in interfaces.sol | ||||
| 	 * @param setId Set token amount at this ID in `InstaMemory` Contract. | ||||
| 	 */ | ||||
| 	function _swap(SwapData memory swapData, uint256 setId) | ||||
| 		internal | ||||
| 		returns (SwapData memory) | ||||
| 	{ | ||||
| 		bool isEthSellToken = address(swapData.sellToken) == ethAddr; | ||||
| 		bool isEthBuyToken = address(swapData.buyToken) == ethAddr; | ||||
| 
 | ||||
| 		swapData.sellToken = isEthSellToken | ||||
| 			? TokenInterface(wethAddr) | ||||
| 			: swapData.sellToken; | ||||
| 		swapData.buyToken = isEthBuyToken | ||||
| 			? TokenInterface(wethAddr) | ||||
| 			: swapData.buyToken; | ||||
| 
 | ||||
| 		convertEthToWeth(isEthSellToken, swapData.sellToken, swapData._sellAmt); | ||||
| 
 | ||||
| 		approve( | ||||
| 			TokenInterface(swapData.sellToken), | ||||
| 			V3_SWAP_ROUTER_ADDRESS, | ||||
| 			swapData._sellAmt | ||||
| 		); | ||||
| 
 | ||||
| 		swapData._buyAmt = _swapHelper(swapData); | ||||
| 
 | ||||
| 		convertWethToEth(isEthBuyToken, swapData.buyToken, swapData._buyAmt); | ||||
| 
 | ||||
| 		setUint(setId, swapData._buyAmt); | ||||
| 
 | ||||
| 		return swapData; | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,12 @@ | |||
| pragma solidity ^0.7.0; | ||||
| 
 | ||||
| import { TokenInterface } from "../../../common/interfaces.sol"; | ||||
| 
 | ||||
| struct SwapData { | ||||
| 	TokenInterface sellToken; | ||||
| 	TokenInterface buyToken; | ||||
| 	uint256 _sellAmt; | ||||
| 	uint256 _buyAmt; | ||||
| 	uint256 unitAmt; | ||||
| 	bytes callData; | ||||
| } | ||||
							
								
								
									
										64
									
								
								contracts/mainnet/connectors/uniswap/v3_auto_router/main.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								contracts/mainnet/connectors/uniswap/v3_auto_router/main.sol
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,64 @@ | |||
| pragma solidity ^0.7.0; | ||||
| pragma experimental ABIEncoderV2; | ||||
| 
 | ||||
| /** | ||||
|  * @title UniswapV3_autoRouter. | ||||
|  * @dev DEX. | ||||
|  */ | ||||
| 
 | ||||
| // import files from common directory | ||||
| import { TokenInterface, MemoryInterface } from "../../../common/interfaces.sol"; | ||||
| import { Stores } from "../../../common/stores.sol"; | ||||
| import { SwapData } from "./interface.sol"; | ||||
| import { Helpers } from "./helpers.sol"; | ||||
| import { Events } from "./events.sol"; | ||||
| 
 | ||||
| abstract contract AutoRouter is Helpers, Events { | ||||
| 	/** | ||||
| 	 * @dev Sell ETH/ERC20_Token using uniswap v3 auto router. | ||||
| 	 * @notice Swap tokens from getting an optimized trade routes | ||||
| 	 * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) | ||||
| 	 * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) | ||||
| 	 * @param sellAmt The amount of the token to sell. | ||||
| 	 * @param unitAmt The amount of buyAmt/sellAmt with slippage. | ||||
| 	 * @param callData Data from Uniswap V3 auto router SDK. | ||||
| 	 * @param setId ID stores the amount of token brought. | ||||
| 	 */ | ||||
| 	function sell( | ||||
| 		address buyAddr, | ||||
| 		address sellAddr, | ||||
| 		uint256 sellAmt, | ||||
| 		uint256 unitAmt, | ||||
| 		bytes calldata callData, | ||||
| 		uint256 setId | ||||
| 	) | ||||
| 		external | ||||
| 		payable | ||||
| 		returns (string memory _eventName, bytes memory _eventParam) | ||||
| 	{ | ||||
| 		SwapData memory swapData = SwapData({ | ||||
| 			buyToken: TokenInterface(buyAddr), | ||||
| 			sellToken: TokenInterface(sellAddr), | ||||
| 			unitAmt: unitAmt, | ||||
| 			callData: callData, | ||||
| 			_sellAmt: sellAmt, | ||||
| 			_buyAmt: 0 | ||||
| 		}); | ||||
| 
 | ||||
| 		swapData = _swap(swapData, setId); | ||||
| 
 | ||||
| 		_eventName = "LogSwap(address,address,uint256,uint256,uint256,uint256)"; | ||||
| 		_eventParam = abi.encode( | ||||
| 			buyAddr, | ||||
| 			sellAddr, | ||||
| 			swapData._buyAmt, | ||||
| 			swapData._sellAmt, | ||||
| 			0, | ||||
| 			setId | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| contract ConnectV2UniswapV3AutoRouter is AutoRouter { | ||||
| 	string public name = "UniswapV3-Auto-Router-v1"; | ||||
| } | ||||
|  | @ -3,67 +3,86 @@ pragma solidity ^0.7.0; | |||
| import { TokenInterface } from "../../../common/interfaces.sol"; | ||||
| import { DSMath } from "../../../common/math.sol"; | ||||
| import { Basic } from "../../../common/basic.sol"; | ||||
| import {SwapData} from "./interface.sol"; | ||||
| import { SwapData } from "./interface.sol"; | ||||
| 
 | ||||
| abstract contract Helpers is DSMath, Basic { | ||||
|     /** | ||||
|      * @dev UniswapV3 Swap Router Address | ||||
|      */ | ||||
|    address internal constant V3_SWAP_ROUTER_ADDRESS = 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45; | ||||
| 	/** | ||||
| 	 * @dev UniswapV3 Swap Router Address | ||||
| 	 */ | ||||
| 	address internal constant V3_SWAP_ROUTER_ADDRESS = | ||||
| 		0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45; | ||||
| 
 | ||||
|      /** | ||||
|      * @dev UniswapV3 swapHelper | ||||
|      * @param swapData - Struct defined in interfaces.sol | ||||
|      */ | ||||
|     function _swapHelper( | ||||
|         SwapData memory swapData | ||||
|     ) internal returns (uint buyAmt) { | ||||
|          | ||||
|         (uint _buyDec, uint _sellDec) = getTokensDec(swapData.buyToken, swapData.sellToken); | ||||
|         uint _sellAmt18 = convertTo18(_sellDec, swapData._sellAmt); | ||||
|         uint _slippageAmt = convert18ToDec(_buyDec, wmul(swapData.unitAmt, _sellAmt18)); | ||||
| 	/** | ||||
| 	 * @dev UniswapV3 swapHelper | ||||
| 	 * @param swapData - Struct defined in interfaces.sol | ||||
| 	 */ | ||||
| 	function _swapHelper(SwapData memory swapData) | ||||
| 		internal | ||||
| 		returns (uint256 buyAmt) | ||||
| 	{ | ||||
| 		(uint256 _buyDec, uint256 _sellDec) = getTokensDec( | ||||
| 			swapData.buyToken, | ||||
| 			swapData.sellToken | ||||
| 		); | ||||
| 		uint256 _sellAmt18 = convertTo18(_sellDec, swapData._sellAmt); | ||||
| 		uint256 _slippageAmt = convert18ToDec( | ||||
| 			_buyDec, | ||||
| 			wmul(swapData.unitAmt, _sellAmt18) | ||||
| 		); | ||||
| 
 | ||||
|         uint initalBal = getTokenBal(swapData.buyToken); | ||||
| 		uint256 initalBal = getTokenBal(swapData.buyToken); | ||||
| 
 | ||||
|         // solium-disable-next-line security/no-call-value | ||||
|         (bool success, ) = V3_SWAP_ROUTER_ADDRESS.call(swapData.callData); | ||||
|         if (!success) revert("uniswapV3-swap-failed"); | ||||
| 		// solium-disable-next-line security/no-call-value | ||||
| 		(bool success, ) = V3_SWAP_ROUTER_ADDRESS.call(swapData.callData); | ||||
| 		if (!success) revert("uniswapV3-swap-failed"); | ||||
| 
 | ||||
|         uint finalBal = getTokenBal(swapData.buyToken); | ||||
| 		uint256 finalBal = getTokenBal(swapData.buyToken); | ||||
| 
 | ||||
|         buyAmt = sub(finalBal, initalBal); | ||||
|         require(_slippageAmt <= buyAmt, "Too much slippage"); | ||||
| 		buyAmt = sub(finalBal, initalBal); | ||||
| 		require(_slippageAmt <= buyAmt, "Too much slippage"); | ||||
| 	} | ||||
| 
 | ||||
|     } | ||||
| 	/** | ||||
| 	 * @dev Gets the swapping data from auto router sdk | ||||
| 	 * @param swapData Struct with multiple swap data defined in interfaces.sol | ||||
| 	 * @param setId Set token amount at this ID in `InstaMemory` Contract. | ||||
| 	 */ | ||||
| 	function _swap(SwapData memory swapData, uint256 setId) | ||||
| 		internal | ||||
| 		returns (SwapData memory) | ||||
| 	{ | ||||
| 		bool isMaticSellToken = address(swapData.sellToken) == maticAddr; | ||||
| 		bool isMaticBuyToken = address(swapData.buyToken) == maticAddr; | ||||
| 
 | ||||
|      /** | ||||
|      * @dev Gets the swapping data from auto router sdk | ||||
|      * @param swapData Struct with multiple swap data defined in interfaces.sol  | ||||
|      * @param setId Set token amount at this ID in `InstaMemory` Contract. | ||||
|      */ | ||||
|     function _swap( | ||||
|         SwapData memory swapData, | ||||
|         uint setId | ||||
|     ) internal returns (SwapData memory) { | ||||
| 		swapData.sellToken = isMaticSellToken | ||||
| 			? TokenInterface(wmaticAddr) | ||||
| 			: swapData.sellToken; | ||||
| 		swapData.buyToken = isMaticBuyToken | ||||
| 			? TokenInterface(wmaticAddr) | ||||
| 			: swapData.buyToken; | ||||
| 
 | ||||
|         bool isMaticSellToken = address(swapData.sellToken) == maticAddr; | ||||
|         bool isMaticBuyToken = address(swapData.buyToken) == maticAddr; | ||||
| 		convertMaticToWmatic( | ||||
| 			isMaticSellToken, | ||||
| 			swapData.sellToken, | ||||
| 			swapData._sellAmt | ||||
| 		); | ||||
| 
 | ||||
|         swapData.sellToken = isMaticSellToken ? TokenInterface(wmaticAddr) : swapData.sellToken; | ||||
|         swapData.buyToken =  isMaticBuyToken ?  TokenInterface(wmaticAddr) : swapData.buyToken; | ||||
| 		approve( | ||||
| 			TokenInterface(swapData.sellToken), | ||||
| 			V3_SWAP_ROUTER_ADDRESS, | ||||
| 			swapData._sellAmt | ||||
| 		); | ||||
| 
 | ||||
|         convertMaticToWmatic(isMaticSellToken, swapData.sellToken, swapData._sellAmt); | ||||
| 		swapData._buyAmt = _swapHelper(swapData); | ||||
| 
 | ||||
|         approve(TokenInterface(swapData.sellToken), V3_SWAP_ROUTER_ADDRESS, swapData._sellAmt); | ||||
|      | ||||
|         swapData._buyAmt = _swapHelper(swapData); | ||||
| 		convertWmaticToMatic( | ||||
| 			isMaticBuyToken, | ||||
| 			swapData.buyToken, | ||||
| 			swapData._buyAmt | ||||
| 		); | ||||
| 
 | ||||
|         convertWmaticToMatic(isMaticBuyToken,swapData.buyToken,swapData._buyAmt); | ||||
| 		setUint(setId, swapData._buyAmt); | ||||
| 
 | ||||
|         setUint(setId, swapData._buyAmt); | ||||
| 
 | ||||
|         return swapData; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 		return swapData; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
							
								
								
									
										308
									
								
								test/mainnet/uniswapV3Router/uniswapV3Router.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										308
									
								
								test/mainnet/uniswapV3Router/uniswapV3Router.test.ts
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,308 @@ | |||
| import hre from "hardhat"; | ||||
| import { expect } from "chai"; | ||||
| const { ethers } = hre; //check
 | ||||
| import { BigNumber } from "bignumber.js"; | ||||
| import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"; | ||||
| import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; | ||||
| import { encodeSpells } from "../../../scripts/tests/encodeSpells"; | ||||
| import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; | ||||
| import { addresses } from "../../../scripts/tests/mainnet/addresses"; | ||||
| import { addLiquidity } from "../../../scripts/tests/addLiquidity"; | ||||
| import { abis } from "../../../scripts/constant/abis"; | ||||
| import { ConnectV2UniswapV3AutoRouter__factory } from "../../../typechain"; | ||||
| import er20abi from "../../../scripts/constant/abi/basics/erc20.json"; | ||||
| import type { Signer, Contract } from "ethers"; | ||||
| import { CurrencyAmount, Token, TradeType, Currency, Percent } from "@uniswap/sdk-core"; | ||||
| import { AlphaRouter } from "@uniswap/smart-order-router"; | ||||
| const provider = new ethers.providers.JsonRpcProvider(process.env.ETH_NODE_URL); | ||||
| const router = new AlphaRouter({ chainId: 1, provider: provider }); | ||||
| 
 | ||||
| describe("Auto Router", function () { | ||||
|   const connectorName = "Auto-Router-test"; | ||||
| 
 | ||||
|   let dsaWallet0: Contract; | ||||
|   let wallet0: Signer, wallet1: Signer; | ||||
|   let masterSigner: Signer; | ||||
|   let instaConnectorsV2: Contract; | ||||
|   let connector: Contract; | ||||
| 
 | ||||
|   // @ts-ignore
 | ||||
|   const provider = new ethers.providers.JsonRpcProvider(hre.config.networks.hardhat.forking.url); | ||||
|   const router = new AlphaRouter({ chainId: 1, provider }); | ||||
| 
 | ||||
|   before(async () => { | ||||
|     await hre.network.provider.request({ | ||||
|       method: "hardhat_reset", | ||||
|       params: [ | ||||
|         { | ||||
|           forking: { | ||||
|             // @ts-ignore
 | ||||
|             jsonRpcUrl: hre.config.networks.hardhat.forking.url | ||||
|           } | ||||
|         } | ||||
|       ] | ||||
|     }); | ||||
|     [wallet0, wallet1] = await ethers.getSigners(); | ||||
| 
 | ||||
|     masterSigner = await getMasterSigner(); | ||||
|     instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); | ||||
|     connector = await deployAndEnableConnector({ | ||||
|       connectorName, | ||||
|       contractArtifact: ConnectV2UniswapV3AutoRouter__factory, | ||||
|       signer: masterSigner, | ||||
|       connectors: instaConnectorsV2 | ||||
|     }); | ||||
|     console.log("Connector address", connector.address); | ||||
|   }); | ||||
| 
 | ||||
|   it("Should have contracts deployed.", async function () { | ||||
|     expect(!!instaConnectorsV2.address).to.be.true; | ||||
|     expect(!!connector.address).to.be.true; | ||||
|     expect(!!(await masterSigner.getAddress())).to.be.true; | ||||
|   }); | ||||
| 
 | ||||
|   describe("DSA wallet setup", function () { | ||||
|     it("Should build DSA v2", async function () { | ||||
|       dsaWallet0 = await buildDSAv2(await wallet0.getAddress()); | ||||
|       expect(!!dsaWallet0.address).to.be.true; | ||||
|     }); | ||||
| 
 | ||||
|     it("Deposit ETH and DAI into DSA wallet", async function () { | ||||
|       await wallet0.sendTransaction({ | ||||
|         to: dsaWallet0.address, | ||||
|         value: ethers.utils.parseEther("10") | ||||
|       }); | ||||
|       await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("5000")); | ||||
|       // console.log(dsaWallet0.address);
 | ||||
|       const daiToken = await ethers.getContractAt( | ||||
|         er20abi, | ||||
|         "0x6b175474e89094c44da98b954eedeac495271d0f" // dai address
 | ||||
|       ); | ||||
| 
 | ||||
|       expect(await daiToken.balanceOf(dsaWallet0.address)).to.be.gte(10); | ||||
|       expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe("Main", function () { | ||||
|     it("should swap the tokens ", async function () { | ||||
|       const buyTokenAddress = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; //usdc
 | ||||
|       const sellTokenAddress = "0x6b175474e89094c44da98b954eedeac495271d0f"; //dai
 | ||||
|       const sellTokenDecimals = 18; | ||||
|       const buyTokenDecimals = 6; | ||||
|       const amount = 1; | ||||
| 
 | ||||
|       const srcAmount = new BigNumber(amount).times(new BigNumber(10).pow(sellTokenDecimals)).toFixed(0); | ||||
|       const sellToken = new Token(1, sellTokenAddress, sellTokenDecimals); | ||||
|       const buyToken = new Token(1, buyTokenAddress, buyTokenDecimals); | ||||
|       const daiAmount = CurrencyAmount.fromRawAmount(sellToken, srcAmount); | ||||
| 
 | ||||
|       const deadline = 1696000000 // Fri Sep 29 2023 15:06:40 GMT+0000
 | ||||
|       const route = await router.route(daiAmount, buyToken , TradeType.EXACT_INPUT, { | ||||
|         recipient: dsaWallet0.address, | ||||
|         slippageTolerance: new Percent(5, 100), | ||||
|         deadline | ||||
|       }); | ||||
|      | ||||
|       const calldata = route?.methodParameters?.calldata; | ||||
|      | ||||
|       const _buyAmount = route?.quote.toFixed(); | ||||
|       const buyTokenAmount = new BigNumber(String(_buyAmount)).times(new BigNumber(10).pow(buyTokenDecimals)).toFixed(0); | ||||
|        | ||||
|        | ||||
|       function caculateUnitAmt( | ||||
|         buyAmount: any, | ||||
|         sellAmount: any, | ||||
|         buyDecimal: any, | ||||
|         sellDecimal: any, | ||||
|         maxSlippage: any | ||||
|       ) { | ||||
|         let unitAmt: any; | ||||
|         unitAmt = new BigNumber(buyAmount) | ||||
|           .dividedBy(10 ** buyDecimal) | ||||
|           .dividedBy(new BigNumber(sellAmount).dividedBy(10 ** sellDecimal)); | ||||
|         unitAmt = unitAmt.multipliedBy((100 - maxSlippage) / 100); | ||||
|         unitAmt = unitAmt.multipliedBy(1e18).toFixed(0); | ||||
|         return unitAmt; | ||||
|       } | ||||
| 
 | ||||
|       const unitAmt = caculateUnitAmt( | ||||
|         buyTokenAmount, | ||||
|         srcAmount, | ||||
|         buyTokenDecimals, | ||||
|         sellTokenDecimals, | ||||
|         1 | ||||
|       ); | ||||
|       const spells = [ | ||||
|         { | ||||
|           connector: connectorName, | ||||
|           method: "sell", | ||||
|           args: [buyTokenAddress, sellTokenAddress, srcAmount, unitAmt, calldata, 0] | ||||
|         } | ||||
|       ]; | ||||
| 
 | ||||
|       const buyTokenContract = await ethers.getContractAt( | ||||
|         er20abi, | ||||
|         buyTokenAddress, | ||||
|       ); | ||||
| 
 | ||||
|       const initialBuyTokenBalance = await buyTokenContract.balanceOf(dsaWallet0.address) | ||||
| 
 | ||||
|       const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet1.getAddress()); | ||||
|       const receipt = await tx.wait(); | ||||
| 
 | ||||
|       const finalBuyTokenBalance = await buyTokenContract.balanceOf(dsaWallet0.address) | ||||
| 
 | ||||
|        | ||||
|       expect(finalBuyTokenBalance).to.be.gt(initialBuyTokenBalance); | ||||
|     }); | ||||
| 
 | ||||
|     it("should swap the tokens when selltoken is eth in the spell", async function () { | ||||
|       const buyTokenAddress = "0x6b175474e89094c44da98b954eedeac495271d0f"; //dai
 | ||||
|       const sellTokenAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; //eth
 | ||||
|       const sellTokenDecimals = 18; | ||||
|       const buyTokenDecimals = 18; | ||||
|       const amount = 1; | ||||
| 
 | ||||
|       const wethAddr = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"; | ||||
| 
 | ||||
|       const srcAmount = new BigNumber(amount).times(new BigNumber(10).pow(sellTokenDecimals)).toFixed(0); | ||||
|       const sellToken = new Token(1, wethAddr, sellTokenDecimals); | ||||
|       const buyToken = new Token(1, buyTokenAddress, buyTokenDecimals); | ||||
|       const sellAmount = CurrencyAmount.fromRawAmount(sellToken, srcAmount); | ||||
| 
 | ||||
|       const deadline = 1696000000 // Fri Sep 29 2023 15:06:40 GMT+0000
 | ||||
|       const route = await router.route(sellAmount, buyToken, TradeType.EXACT_INPUT, { | ||||
|         recipient: dsaWallet0.address, | ||||
|         slippageTolerance: new Percent(5, 100), | ||||
|         deadline | ||||
|       }); | ||||
|      | ||||
|       const calldata = route?.methodParameters?.calldata; | ||||
|      | ||||
|       const _buyAmount = route?.quote.toFixed(); | ||||
|       const buyTokenAmount = new BigNumber(String(_buyAmount)).times(new BigNumber(10).pow(buyTokenDecimals)).toFixed(0); | ||||
|        | ||||
|     | ||||
|       function caculateUnitAmt( | ||||
|         buyAmount: any, | ||||
|         sellAmount: any, | ||||
|         buyDecimal: any, | ||||
|         sellDecimal: any, | ||||
|         maxSlippage: any | ||||
|       ) { | ||||
|         let unitAmt: any; | ||||
|         unitAmt = new BigNumber(buyAmount) | ||||
|           .dividedBy(10 ** buyDecimal) | ||||
|           .dividedBy(new BigNumber(sellAmount).dividedBy(10 ** sellDecimal)); | ||||
|         unitAmt = unitAmt.multipliedBy((100 - maxSlippage) / 100); | ||||
|         unitAmt = unitAmt.multipliedBy(1e18).toFixed(0); | ||||
|         return unitAmt; | ||||
|       } | ||||
| 
 | ||||
|       const unitAmt = caculateUnitAmt( | ||||
|         buyTokenAmount, | ||||
|         srcAmount, | ||||
|         buyTokenDecimals, | ||||
|         sellTokenDecimals, | ||||
|         1 | ||||
|       ); | ||||
| 
 | ||||
|       const spells = [ | ||||
|         { | ||||
|           connector: connectorName, | ||||
|           method: "sell", | ||||
|           args: [buyTokenAddress, sellTokenAddress, srcAmount, unitAmt, calldata, 0] | ||||
|         } | ||||
|       ]; | ||||
| 
 | ||||
|       const buyTokenContract = await ethers.getContractAt( | ||||
|         er20abi, | ||||
|         buyTokenAddress, | ||||
|       ); | ||||
| 
 | ||||
|       const initialBuyTokenBalance = await buyTokenContract.balanceOf(dsaWallet0.address) | ||||
| 
 | ||||
|       const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet1.getAddress()); | ||||
|       const receipt = await tx.wait(); | ||||
| 
 | ||||
|       const finalBuyTokenBalance = await buyTokenContract.balanceOf(dsaWallet0.address) | ||||
| 
 | ||||
|        | ||||
|       expect(finalBuyTokenBalance).to.be.gt(initialBuyTokenBalance); | ||||
|     }); | ||||
| 
 | ||||
|     it("should swap the tokens when buytoken is weth in the spell", async function () { | ||||
|       const buyTokenAddress = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"; // weth
 | ||||
|       const sellTokenAddress = "0x6b175474e89094c44da98b954eedeac495271d0f"; // dai
 | ||||
|       const sellTokenDecimals = 18; | ||||
|       const buyTokenDecimals = 18; | ||||
|       const amount = 4000; | ||||
| 
 | ||||
|       const srcAmount = new BigNumber(amount).times(new BigNumber(10).pow(sellTokenDecimals)).toFixed(0); | ||||
|       const sellToken = new Token(1, sellTokenAddress, sellTokenDecimals); | ||||
|       const buyToken = new Token(1, buyTokenAddress, buyTokenDecimals); | ||||
|       const daiAmount = CurrencyAmount.fromRawAmount(sellToken, srcAmount); | ||||
| 
 | ||||
|       const deadline = 1696000000 // Fri Sep 29 2023 15:06:40 GMT+0000
 | ||||
|       const route = await router.route(daiAmount, buyToken , TradeType.EXACT_INPUT, { | ||||
|         recipient: dsaWallet0.address, | ||||
|         slippageTolerance: new Percent(5, 100), | ||||
|         deadline | ||||
|       }); | ||||
|      | ||||
|       const calldata = route?.methodParameters?.calldata; | ||||
|      | ||||
|       const _buyAmount = route?.quote.toFixed(); | ||||
|       const buyTokenAmount = new BigNumber(String(_buyAmount)).times(new BigNumber(10).pow(buyTokenDecimals)).toFixed(0); | ||||
|        | ||||
|     | ||||
|       function caculateUnitAmt( | ||||
|         buyAmount: any, | ||||
|         sellAmount: any, | ||||
|         buyDecimal: any, | ||||
|         sellDecimal: any, | ||||
|         maxSlippage: any | ||||
|       ) { | ||||
|         let unitAmt: any; | ||||
|         unitAmt = new BigNumber(buyAmount) | ||||
|           .dividedBy(10 ** buyDecimal) | ||||
|           .dividedBy(new BigNumber(sellAmount).dividedBy(10 ** sellDecimal)); | ||||
|         unitAmt = unitAmt.multipliedBy((100 - maxSlippage) / 100); | ||||
|         unitAmt = unitAmt.multipliedBy(1e18).toFixed(0); | ||||
|         return unitAmt; | ||||
|       } | ||||
| 
 | ||||
|       const unitAmt = caculateUnitAmt( | ||||
|         buyTokenAmount, | ||||
|         srcAmount, | ||||
|         buyTokenDecimals, | ||||
|         sellTokenDecimals, | ||||
|         1 | ||||
|       ); | ||||
|      | ||||
|       const spells = [ | ||||
|         { | ||||
|           connector: connectorName, | ||||
|           method: "sell", | ||||
|           args: [buyTokenAddress, sellTokenAddress, srcAmount, unitAmt, calldata, 0] | ||||
|         } | ||||
|       ]; | ||||
| 
 | ||||
|       const buyTokenContract = await ethers.getContractAt( | ||||
|         er20abi, | ||||
|         buyTokenAddress, | ||||
|       ); | ||||
| 
 | ||||
|       const initialBuyTokenBalance = await buyTokenContract.balanceOf(dsaWallet0.address) | ||||
| 
 | ||||
|       const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet1.getAddress()); | ||||
|       const receipt = await tx.wait(); | ||||
| 
 | ||||
|       const finalBuyTokenBalance = await buyTokenContract.balanceOf(dsaWallet0.address) | ||||
| 
 | ||||
|        | ||||
|       expect(finalBuyTokenBalance).to.be.gt(initialBuyTokenBalance); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 0xPradyuman
						0xPradyuman