-
-
Save BlockmanCodes/52ede9384fd774ed18c5dea5912fbe3d to your computer and use it in GitHub Desktop.
| const { SwapRouter } = require('@uniswap/universal-router-sdk') | |
| const { TradeType, Ether, Token, CurrencyAmount, Percent } = require('@uniswap/sdk-core') | |
| const { Trade: V2Trade } = require('@uniswap/v2-sdk') | |
| const { Pool, nearestUsableTick, TickMath, TICK_SPACINGS, FeeAmount, Trade: V3Trade, Route: RouteV3 } = require('@uniswap/v3-sdk') | |
| const { MixedRouteTrade, Trade: RouterTrade } = require('@uniswap/router-sdk') | |
| const IUniswapV3Pool = require('@uniswap/v3-core/artifacts/contracts/UniswapV3Pool.sol/UniswapV3Pool.json') | |
| const JSBI = require('jsbi') | |
| const erc20Abi = require('../abis/erc20.json') | |
| const hardhat = require("hardhat"); | |
| const provider = hardhat.ethers.provider; | |
| const ETHER = Ether.onChain(1) | |
| const WETH = new Token(1, '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', 18, 'WETH', 'Wrapped Ether') | |
| const USDC = new Token(1, '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', 6, 'USDC', 'USD Coin') | |
| const wethContract = new hardhat.ethers.Contract(WETH.address, erc20Abi, provider) | |
| const usdcContract = new hardhat.ethers.Contract(USDC.address, erc20Abi, provider) | |
| async function getPool(tokenA, tokenB, feeAmount) { | |
| const [token0, token1] = tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA] | |
| const poolAddress = Pool.getAddress(token0, token1, feeAmount) | |
| const contract = new hardhat.ethers.Contract(poolAddress, IUniswapV3Pool.abi, provider) | |
| let liquidity = await contract.liquidity() | |
| let { sqrtPriceX96, tick } = await contract.slot0() | |
| liquidity = JSBI.BigInt(liquidity.toString()) | |
| sqrtPriceX96 = JSBI.BigInt(sqrtPriceX96.toString()) | |
| return new Pool(token0, token1, feeAmount, sqrtPriceX96, liquidity, tick, [ | |
| { | |
| index: nearestUsableTick(TickMath.MIN_TICK, TICK_SPACINGS[feeAmount]), | |
| liquidityNet: liquidity, | |
| liquidityGross: liquidity, | |
| }, | |
| { | |
| index: nearestUsableTick(TickMath.MAX_TICK, TICK_SPACINGS[feeAmount]), | |
| liquidityNet: JSBI.multiply(liquidity, JSBI.BigInt('-1')), | |
| liquidityGross: liquidity, | |
| }, | |
| ]) | |
| } | |
| function swapOptions(options) { | |
| return Object.assign( | |
| { | |
| slippageTolerance: new Percent(5, 100), | |
| recipient: RECIPIENT, | |
| }, | |
| options | |
| ) | |
| } | |
| function buildTrade(trades) { | |
| return new RouterTrade({ | |
| v2Routes: trades | |
| .filter((trade) => trade instanceof V2Trade) | |
| .map((trade) => ({ | |
| routev2: trade.route, | |
| inputAmount: trade.inputAmount, | |
| outputAmount: trade.outputAmount, | |
| })), | |
| v3Routes: trades | |
| .filter((trade) => trade instanceof V3Trade) | |
| .map((trade) => ({ | |
| routev3: trade.route, | |
| inputAmount: trade.inputAmount, | |
| outputAmount: trade.outputAmount, | |
| })), | |
| mixedRoutes: trades | |
| .filter((trade) => trade instanceof MixedRouteTrade) | |
| .map((trade) => ({ | |
| mixedRoute: trade.route, | |
| inputAmount: trade.inputAmount, | |
| outputAmount: trade.outputAmount, | |
| })), | |
| tradeType: trades[0].tradeType, | |
| }) | |
| } | |
| const RECIPIENT = '0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B' | |
| async function main() { | |
| const signer = await hardhat.ethers.getImpersonatedSigner(RECIPIENT); | |
| const WETH_USDC_V3 = await getPool(WETH, USDC, FeeAmount.MEDIUM) | |
| const inputEther = hardhat.ethers.utils.parseEther('1').toString() | |
| const trade = await V3Trade.fromRoute( | |
| new RouteV3([WETH_USDC_V3], ETHER, USDC), | |
| CurrencyAmount.fromRawAmount(ETHER, inputEther), | |
| TradeType.EXACT_INPUT | |
| ) | |
| const routerTrade = buildTrade([trade]) | |
| const opts = swapOptions({}) | |
| const params = SwapRouter.swapERC20CallParameters(routerTrade, opts) | |
| let ethBalance | |
| let wethBalance | |
| let usdcBalance | |
| ethBalance = await provider.getBalance(RECIPIENT) | |
| wethBalance = await wethContract.balanceOf(RECIPIENT) | |
| usdcBalance = await usdcContract.balanceOf(RECIPIENT) | |
| console.log('---------------------------- BEFORE') | |
| console.log('ethBalance', hardhat.ethers.utils.formatUnits(ethBalance, 18)) | |
| console.log('wethBalance', hardhat.ethers.utils.formatUnits(wethBalance, 18)) | |
| console.log('usdcBalance', hardhat.ethers.utils.formatUnits(usdcBalance, 6)) | |
| const tx = await signer.sendTransaction({ | |
| data: params.calldata, | |
| to: '0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B', | |
| value: params.value, | |
| from: RECIPIENT, | |
| }) | |
| const receipt = await tx.wait() | |
| console.log('---------------------------- SUCCESS?') | |
| console.log('status', receipt.status) | |
| ethBalance = await provider.getBalance(RECIPIENT) | |
| wethBalance = await wethContract.balanceOf(RECIPIENT) | |
| usdcBalance = await usdcContract.balanceOf(RECIPIENT) | |
| console.log('---------------------------- AFTER') | |
| console.log('ethBalance', hardhat.ethers.utils.formatUnits(ethBalance, 18)) | |
| console.log('wethBalance', hardhat.ethers.utils.formatUnits(wethBalance, 18)) | |
| console.log('usdcBalance', hardhat.ethers.utils.formatUnits(usdcBalance, 6)) | |
| } | |
| /* | |
| node scripts/01_simpleSwap.js | |
| */ | |
| main() | |
| .then(() => process.exit(0)) | |
| .catch((error) => { | |
| console.error(error); | |
| process.exit(1); | |
| }); |
| [ | |
| { | |
| "inputs": [], | |
| "stateMutability": "nonpayable", | |
| "type": "constructor" | |
| }, | |
| { | |
| "anonymous": false, | |
| "inputs": [ | |
| { | |
| "indexed": true, | |
| "internalType": "address", | |
| "name": "owner", | |
| "type": "address" | |
| }, | |
| { | |
| "indexed": true, | |
| "internalType": "address", | |
| "name": "spender", | |
| "type": "address" | |
| }, | |
| { | |
| "indexed": false, | |
| "internalType": "uint256", | |
| "name": "value", | |
| "type": "uint256" | |
| } | |
| ], | |
| "name": "Approval", | |
| "type": "event" | |
| }, | |
| { | |
| "anonymous": false, | |
| "inputs": [ | |
| { | |
| "indexed": true, | |
| "internalType": "address", | |
| "name": "from", | |
| "type": "address" | |
| }, | |
| { | |
| "indexed": true, | |
| "internalType": "address", | |
| "name": "to", | |
| "type": "address" | |
| }, | |
| { | |
| "indexed": false, | |
| "internalType": "uint256", | |
| "name": "value", | |
| "type": "uint256" | |
| } | |
| ], | |
| "name": "Transfer", | |
| "type": "event" | |
| }, | |
| { | |
| "inputs": [ | |
| { | |
| "internalType": "address", | |
| "name": "owner", | |
| "type": "address" | |
| }, | |
| { | |
| "internalType": "address", | |
| "name": "spender", | |
| "type": "address" | |
| } | |
| ], | |
| "name": "allowance", | |
| "outputs": [ | |
| { | |
| "internalType": "uint256", | |
| "name": "", | |
| "type": "uint256" | |
| } | |
| ], | |
| "stateMutability": "view", | |
| "type": "function" | |
| }, | |
| { | |
| "inputs": [ | |
| { | |
| "internalType": "address", | |
| "name": "spender", | |
| "type": "address" | |
| }, | |
| { | |
| "internalType": "uint256", | |
| "name": "amount", | |
| "type": "uint256" | |
| } | |
| ], | |
| "name": "approve", | |
| "outputs": [ | |
| { | |
| "internalType": "bool", | |
| "name": "", | |
| "type": "bool" | |
| } | |
| ], | |
| "stateMutability": "nonpayable", | |
| "type": "function" | |
| }, | |
| { | |
| "inputs": [ | |
| { | |
| "internalType": "address", | |
| "name": "account", | |
| "type": "address" | |
| } | |
| ], | |
| "name": "balanceOf", | |
| "outputs": [ | |
| { | |
| "internalType": "uint256", | |
| "name": "", | |
| "type": "uint256" | |
| } | |
| ], | |
| "stateMutability": "view", | |
| "type": "function" | |
| }, | |
| { | |
| "inputs": [], | |
| "name": "decimals", | |
| "outputs": [ | |
| { | |
| "internalType": "uint8", | |
| "name": "", | |
| "type": "uint8" | |
| } | |
| ], | |
| "stateMutability": "view", | |
| "type": "function" | |
| }, | |
| { | |
| "inputs": [ | |
| { | |
| "internalType": "address", | |
| "name": "spender", | |
| "type": "address" | |
| }, | |
| { | |
| "internalType": "uint256", | |
| "name": "subtractedValue", | |
| "type": "uint256" | |
| } | |
| ], | |
| "name": "decreaseAllowance", | |
| "outputs": [ | |
| { | |
| "internalType": "bool", | |
| "name": "", | |
| "type": "bool" | |
| } | |
| ], | |
| "stateMutability": "nonpayable", | |
| "type": "function" | |
| }, | |
| { | |
| "inputs": [ | |
| { | |
| "internalType": "address", | |
| "name": "spender", | |
| "type": "address" | |
| }, | |
| { | |
| "internalType": "uint256", | |
| "name": "addedValue", | |
| "type": "uint256" | |
| } | |
| ], | |
| "name": "increaseAllowance", | |
| "outputs": [ | |
| { | |
| "internalType": "bool", | |
| "name": "", | |
| "type": "bool" | |
| } | |
| ], | |
| "stateMutability": "nonpayable", | |
| "type": "function" | |
| }, | |
| { | |
| "inputs": [], | |
| "name": "name", | |
| "outputs": [ | |
| { | |
| "internalType": "string", | |
| "name": "", | |
| "type": "string" | |
| } | |
| ], | |
| "stateMutability": "view", | |
| "type": "function" | |
| }, | |
| { | |
| "inputs": [], | |
| "name": "symbol", | |
| "outputs": [ | |
| { | |
| "internalType": "string", | |
| "name": "", | |
| "type": "string" | |
| } | |
| ], | |
| "stateMutability": "view", | |
| "type": "function" | |
| }, | |
| { | |
| "inputs": [], | |
| "name": "totalSupply", | |
| "outputs": [ | |
| { | |
| "internalType": "uint256", | |
| "name": "", | |
| "type": "uint256" | |
| } | |
| ], | |
| "stateMutability": "view", | |
| "type": "function" | |
| }, | |
| { | |
| "inputs": [ | |
| { | |
| "internalType": "address", | |
| "name": "to", | |
| "type": "address" | |
| }, | |
| { | |
| "internalType": "uint256", | |
| "name": "amount", | |
| "type": "uint256" | |
| } | |
| ], | |
| "name": "transfer", | |
| "outputs": [ | |
| { | |
| "internalType": "bool", | |
| "name": "", | |
| "type": "bool" | |
| } | |
| ], | |
| "stateMutability": "nonpayable", | |
| "type": "function" | |
| }, | |
| { | |
| "inputs": [ | |
| { | |
| "internalType": "address", | |
| "name": "from", | |
| "type": "address" | |
| }, | |
| { | |
| "internalType": "address", | |
| "name": "to", | |
| "type": "address" | |
| }, | |
| { | |
| "internalType": "uint256", | |
| "name": "amount", | |
| "type": "uint256" | |
| } | |
| ], | |
| "name": "transferFrom", | |
| "outputs": [ | |
| { | |
| "internalType": "bool", | |
| "name": "", | |
| "type": "bool" | |
| } | |
| ], | |
| "stateMutability": "nonpayable", | |
| "type": "function" | |
| } | |
| ] |
| require("@nomiclabs/hardhat-waffle"); | |
| /** @type import('hardhat/config').HardhatUserConfig */ | |
| module.exports = { | |
| solidity: "0.8.18", | |
| networks: { | |
| hardhat: { | |
| forking: { | |
| url: "https://mainnet.infura.io/v3/<YOUR_KEY>" | |
| } | |
| } | |
| } | |
| }; |
| { | |
| "name": "tutorials", | |
| "version": "1.0.0", | |
| "description": "", | |
| "main": "index.js", | |
| "scripts": { | |
| "test": "echo \"Error: no test specified\" && exit 1" | |
| }, | |
| "keywords": [], | |
| "author": "", | |
| "license": "ISC", | |
| "dependencies": { | |
| "@nomiclabs/hardhat-ethers": "^2.2.3", | |
| "@nomiclabs/hardhat-waffle": "^2.0.6", | |
| "@types/sinon-chai": "^3.2.9", | |
| "@uniswap/sdk": "^3.0.3", | |
| "@uniswap/sdk-core": "^4.0.2", | |
| "@uniswap/smart-order-router": "^3.13.2-hotfix2", | |
| "@uniswap/v3-core": "^1.0.1", | |
| "@uniswap/v3-periphery": "^1.4.3", | |
| "@uniswap/v3-sdk": "^3.9.0", | |
| "ethereum-waffle": "^4.0.10", | |
| "ethers": "^5.7.2", | |
| "hardhat": "^2.14.0" | |
| } | |
| } |
Invariant failed: WRAPPED . cannot run this code on bsc after modified params.
got this error when swapping on V2 pool
Error: Unexpected pool type in route when constructing trade object
Here is the code to calculate the trade instance:
let route = new RouteV2([pool], nativeEth, token1)
let trade = new V2Trade(route,CurrencyAmount.fromRawAmount(nativeEth, inputEther),TradeType.EXACT_INPUT )
let routerTrade = buildTrade([trade])
what kind of V2 pool format should I use in RouterTrade? Thanks.
TypeError: SwapRouter.swapERC20CallParameters is not a function
TypeError: SwapRouter.swapERC20CallParameters is not a function
update dependences
"@uniswap/sdk": "^3.0.3",
"@uniswap/sdk-core": "^6.1.1",
"@uniswap/smart-order-router": "^4.9.2",
"@uniswap/universal-router-sdk": "^4.7.0",
"@uniswap/v3-core": "^1.0.1",
"@uniswap/v3-periphery": "^1.4.3",
"@uniswap/v3-sdk": "^3.9.0",
and use
const params = SwapRouter.swapCallParameters(routerTrade, opts)
is working for me
No it is not possible we need to wrap it to WETH first.