Skip to content

Commit

Permalink
fix(v4-sdk): Encode all V4 routes with pathInputs/Outputs instead of …
Browse files Browse the repository at this point in the history
…original ones that may involve wrap/unwrap (#163)
  • Loading branch information
ewilz authored Oct 10, 2024
1 parent 45ed414 commit 9feb334
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 14 deletions.
65 changes: 56 additions & 9 deletions sdks/v4-sdk/src/utils/encodeRouteToPath.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { Ether, Token } from '@uniswap/sdk-core'
import { Ether, Token, WETH9 } from '@uniswap/sdk-core'
import { encodeSqrtRatioX96 } from '@uniswap/v3-sdk'
import { Route } from '../entities/route'
import { Pool } from '../entities/pool'
import { encodeRouteToPath } from './encodeRouteToPath'
import { ADDRESS_ZERO, FEE_AMOUNT_MEDIUM, TICK_SPACING_TEN } from '../internalConstants'

const eth = Ether.onChain(1)
const currency1 = new Token(1, '0x0000000000000000000000000000000000000001', 18, 't1')
const currency2 = new Token(1, '0x0000000000000000000000000000000000000002', 18, 't2')
const currency3 = new Token(1, '0x0000000000000000000000000000000000000003', 18, 't3')
const weth = WETH9[1]
const currency1 = new Token(1, '0x1111111111111111111111111111111111111111', 18, 't1')
const currency2 = new Token(1, '0x2222222222222222222222222222222222222222', 18, 't2')
const currency3 = new Token(1, '0x3333333333333333333333333333333333333333', 18, 't3')

const pool_eth_1 = new Pool(
eth,
Expand Down Expand Up @@ -52,21 +53,21 @@ describe('RouterPlanner', () => {
it('encodes the correct route for exactIn', async () => {
const expected = [
{
intermediateCurrency: '0x0000000000000000000000000000000000000001',
intermediateCurrency: '0x1111111111111111111111111111111111111111',
fee: 3000,
tickSpacing: 10,
hooks: '0x0000000000000000000000000000000000000000',
hookData: '0x',
},
{
intermediateCurrency: '0x0000000000000000000000000000000000000002',
intermediateCurrency: '0x2222222222222222222222222222222222222222',
fee: 3000,
tickSpacing: 10,
hooks: '0x0000000000000000000000000000000000000000',
hookData: '0x',
},
{
intermediateCurrency: '0x0000000000000000000000000000000000000003',
intermediateCurrency: '0x3333333333333333333333333333333333333333',
fee: 3000,
tickSpacing: 10,
hooks: '0x0000000000000000000000000000000000000000',
Expand All @@ -88,14 +89,14 @@ describe('RouterPlanner', () => {
hookData: '0x',
},
{
intermediateCurrency: '0x0000000000000000000000000000000000000001',
intermediateCurrency: '0x1111111111111111111111111111111111111111',
fee: 3000,
tickSpacing: 10,
hooks: '0x0000000000000000000000000000000000000000',
hookData: '0x',
},
{
intermediateCurrency: '0x0000000000000000000000000000000000000002',
intermediateCurrency: '0x2222222222222222222222222222222222222222',
fee: 3000,
tickSpacing: 10,
hooks: '0x0000000000000000000000000000000000000000',
Expand All @@ -105,4 +106,50 @@ describe('RouterPlanner', () => {

expect(encodeRouteToPath(route, exactOutput)).toEqual(expected)
})

it('encodes the correct path when route has a different output than route.pathOutput', async () => {
const newRoute = new Route([pool_1_2, pool_eth_1], currency2, weth)
const exactOutput = true
const expected = [
{
intermediateCurrency: '0x2222222222222222222222222222222222222222',
fee: 3000,
tickSpacing: 10,
hooks: '0x0000000000000000000000000000000000000000',
hookData: '0x',
},
{
intermediateCurrency: '0x1111111111111111111111111111111111111111',
fee: 3000,
tickSpacing: 10,
hooks: '0x0000000000000000000000000000000000000000',
hookData: '0x',
},
]

expect(encodeRouteToPath(newRoute, exactOutput)).toEqual(expected)
})

it('encodes the correct path when route has a different input than route.pathInput', async () => {
const newRoute = new Route([pool_eth_1, pool_1_2], weth, currency2)
const exactOutput = false
const expected = [
{
intermediateCurrency: '0x1111111111111111111111111111111111111111',
fee: 3000,
tickSpacing: 10,
hooks: '0x0000000000000000000000000000000000000000',
hookData: '0x',
},
{
intermediateCurrency: '0x2222222222222222222222222222222222222222',
fee: 3000,
tickSpacing: 10,
hooks: '0x0000000000000000000000000000000000000000',
hookData: '0x',
},
]

expect(encodeRouteToPath(newRoute, exactOutput)).toEqual(expected)
})
})
2 changes: 1 addition & 1 deletion sdks/v4-sdk/src/utils/encodeRouteToPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export type PathKey = {
}

export const encodeRouteToPath = (route: Route<Currency, Currency>, exactOutput?: boolean): PathKey[] => {
let startingCurrency = exactOutput ? route.output : route.input
let startingCurrency = exactOutput ? route.pathOutput : route.pathInput
let pools = exactOutput ? route.pools.reverse() : route.pools
let pathKeys: PathKey[] = []

Expand Down
37 changes: 35 additions & 2 deletions sdks/v4-sdk/src/utils/v4Planner.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BigNumber } from 'ethers'
import JSBI from 'jsbi'
import { CurrencyAmount, Percent, TradeType, Token, WETH9 } from '@uniswap/sdk-core'
import { CurrencyAmount, Ether, Percent, TradeType, Token, WETH9 } from '@uniswap/sdk-core'
import { encodeSqrtRatioX96, nearestUsableTick, TickMath } from '@uniswap/v3-sdk'
import { Pool } from '../entities/pool'
import { Trade } from '../entities/trade'
Expand All @@ -24,6 +24,7 @@ const TICKLIST = [
},
]

const ETHER = Ether.onChain(1)
export const USDC = new Token(1, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'USDC', 'USD Coin')
export const DAI = new Token(1, '0x6B175474E89094C44Da98b954EedeAC495271d0F', 18, 'DAI', 'DAI Stablecoin')
export const USDC_WETH = new Pool(
Expand Down Expand Up @@ -135,6 +136,38 @@ describe('RouterPlanner', () => {
)
})

it('completes a v4 exactOut 2 hop swap where route.pathOutput is different than route.output', async () => {
const route = new Route([DAI_USDC, USDC_WETH], DAI, ETHER)
const slippageTolerance = new Percent('5')
const trade = await Trade.fromRoute(
route,
CurrencyAmount.fromRawAmount(ETHER, ONE_ETHER.toString()),
TradeType.EXACT_OUTPUT
)
planner.addTrade(trade, slippageTolerance)

expect(planner.actions).toEqual('0x07')
expect(planner.params[0]).toEqual(
'0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000000000000000000bb8000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000bb8000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000'
)
})

it('completes a v4 exactIn 2 hop swap where route.pathInput is different than route.input', async () => {
const route = new Route([USDC_WETH, DAI_USDC], ETHER, DAI)
const slippageTolerance = new Percent('5')
const trade = await Trade.fromRoute(
route,
CurrencyAmount.fromRawAmount(ETHER, ONE_ETHER.toString()),
TradeType.EXACT_INPUT
)
planner.addTrade(trade, slippageTolerance)

expect(planner.actions).toEqual('0x05')
expect(planner.params[0]).toEqual(
'0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000bb8000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000000000000000000bb8000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000'
)
})

it('throws an error if adding exactOut trade without slippage tolerance', async () => {
const route = new Route([DAI_USDC, USDC_WETH], DAI, WETH9[1])
const trade = await Trade.fromRoute(
Expand Down Expand Up @@ -197,7 +230,7 @@ describe('RouterPlanner', () => {
})
})

describe('addTrade', () => {
describe('addTake', () => {
it('completes a take without a specified amount', async () => {
const recipient = '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
planner.addTake(DAI, recipient)
Expand Down
4 changes: 2 additions & 2 deletions sdks/v4-sdk/src/utils/v4Planner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ export class V4Planner {

const actionType = exactOutput ? Actions.SWAP_EXACT_OUT : Actions.SWAP_EXACT_IN

const currencyIn = currencyAddress(trade.inputAmount.currency)
const currencyOut = currencyAddress(trade.outputAmount.currency)
const currencyIn = currencyAddress(trade.route.pathInput)
const currencyOut = currencyAddress(trade.route.pathOutput)

this.addAction(actionType, [
exactOutput
Expand Down

0 comments on commit 9feb334

Please sign in to comment.