From 2a9a6c0e56eb236ea4bfe7ec86f80014e559b8c2 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Thu, 30 Jan 2025 16:05:43 -0500 Subject: [PATCH 1/7] special case eth, weth fake pool --- .../src/utils/encodeMixedRouteToPath.ts | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/sdks/router-sdk/src/utils/encodeMixedRouteToPath.ts b/sdks/router-sdk/src/utils/encodeMixedRouteToPath.ts index eca13741e..aef2c3453 100644 --- a/sdks/router-sdk/src/utils/encodeMixedRouteToPath.ts +++ b/sdks/router-sdk/src/utils/encodeMixedRouteToPath.ts @@ -34,14 +34,21 @@ export function encodeMixedRouteToPath(route: MixedRouteSDK) const currencyOut = currencyIn.equals(pool.token0) ? pool.token1 : pool.token0 if (pool instanceof V4Pool) { - const v4Fee = pool.fee + MIXED_QUOTER_V2_V4_FEE_PATH_PLACEHOLDER - path.push( - v4Fee, - pool.tickSpacing, - pool.hooks, - currencyOut.isNative ? ADDRESS_ZERO : currencyOut.wrapped.address - ) - types.push('uint24', 'uint24', 'address', 'address') + // a tickSpacing of 0 indicates a "fake" v4 pool where the quote actually requires a wrap or unwrap + if (pool.tickSpacing == 0) { + let wrapOrUnwrapEncoding = 0 + path.push(wrapOrUnwrapEncoding, currencyOut.isNative ? ADDRESS_ZERO : currencyOut.wrapped.address) + types.push('uint8', 'address') + } else { + const v4Fee = pool.fee + MIXED_QUOTER_V2_V4_FEE_PATH_PLACEHOLDER + path.push( + v4Fee, + pool.tickSpacing, + pool.hooks, + currencyOut.isNative ? ADDRESS_ZERO : currencyOut.wrapped.address + ) + types.push('uint24', 'uint24', 'address', 'address') + } } else if (pool instanceof V3Pool) { const v3Fee = pool.fee + MIXED_QUOTER_V2_V3_FEE_PATH_PLACEHOLDER path.push(v3Fee, currencyOut.wrapped.address) From 66ed4c18df3af5099f5f79df2363e25dc51b824e Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Thu, 30 Jan 2025 16:32:27 -0500 Subject: [PATCH 2/7] comments --- sdks/router-sdk/src/utils/encodeMixedRouteToPath.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdks/router-sdk/src/utils/encodeMixedRouteToPath.ts b/sdks/router-sdk/src/utils/encodeMixedRouteToPath.ts index aef2c3453..0e2978bc5 100644 --- a/sdks/router-sdk/src/utils/encodeMixedRouteToPath.ts +++ b/sdks/router-sdk/src/utils/encodeMixedRouteToPath.ts @@ -35,7 +35,7 @@ export function encodeMixedRouteToPath(route: MixedRouteSDK) if (pool instanceof V4Pool) { // a tickSpacing of 0 indicates a "fake" v4 pool where the quote actually requires a wrap or unwrap - if (pool.tickSpacing == 0) { + if (pool.tickSpacing === 0) { let wrapOrUnwrapEncoding = 0 path.push(wrapOrUnwrapEncoding, currencyOut.isNative ? ADDRESS_ZERO : currencyOut.wrapped.address) types.push('uint8', 'address') From 4172d6e7248aa278357f5c541a8035bdbcf6c7d1 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Thu, 30 Jan 2025 23:17:07 -0500 Subject: [PATCH 3/7] comments --- sdks/router-sdk/src/utils/encodeMixedRouteToPath.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdks/router-sdk/src/utils/encodeMixedRouteToPath.ts b/sdks/router-sdk/src/utils/encodeMixedRouteToPath.ts index 0e2978bc5..f7088f98b 100644 --- a/sdks/router-sdk/src/utils/encodeMixedRouteToPath.ts +++ b/sdks/router-sdk/src/utils/encodeMixedRouteToPath.ts @@ -35,8 +35,9 @@ export function encodeMixedRouteToPath(route: MixedRouteSDK) if (pool instanceof V4Pool) { // a tickSpacing of 0 indicates a "fake" v4 pool where the quote actually requires a wrap or unwrap + // the fake v4 pool will always have native as token0 and wrapped native as token1 if (pool.tickSpacing === 0) { - let wrapOrUnwrapEncoding = 0 + const wrapOrUnwrapEncoding = 0 path.push(wrapOrUnwrapEncoding, currencyOut.isNative ? ADDRESS_ZERO : currencyOut.wrapped.address) types.push('uint8', 'address') } else { From 25312d6f817e2207afaf98c4b19284a841c39a95 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Thu, 30 Jan 2025 23:56:29 -0500 Subject: [PATCH 4/7] add unit test --- .../src/utils/encodeMixedRouteToPath.test.ts | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/sdks/router-sdk/src/utils/encodeMixedRouteToPath.test.ts b/sdks/router-sdk/src/utils/encodeMixedRouteToPath.test.ts index 500f5ee18..19ad24ea1 100644 --- a/sdks/router-sdk/src/utils/encodeMixedRouteToPath.test.ts +++ b/sdks/router-sdk/src/utils/encodeMixedRouteToPath.test.ts @@ -31,6 +31,16 @@ describe('#encodeMixedRouteToPath', () => { 0, [] ) + const fake_v4_eth_weth_pool = new V4Pool( + weth, + ETHER, + FeeAmount.MEDIUM, + 0, + ADDRESS_ZERO, + encodeSqrtRatioX96(1, 1), + 0, + 0 + ) const pair_0_1 = new Pair(CurrencyAmount.fromRawAmount(token0, '100'), CurrencyAmount.fromRawAmount(token1, '200')) const pair_1_2 = new Pair(CurrencyAmount.fromRawAmount(token1, '150'), CurrencyAmount.fromRawAmount(token2, '150')) @@ -61,6 +71,8 @@ describe('#encodeMixedRouteToPath', () => { const route_eth_V4_0_V3_1 = new MixedRouteSDK([pool_V4_0_eth, pool_V3_0_1_medium], ETHER, token1) const route_eth_V3_0_V4_1 = new MixedRouteSDK([pool_V3_0_weth, pool_V4_0_1], ETHER, token1) + const route_1_v2_weth_v0_eth_v4_token0 = new MixedRouteSDK([pair_1_weth, fake_v4_eth_weth_pool, pool_V4_0_eth], token1, token0) + describe('pure V3', () => { it('packs them for exact input single hop', () => { expect(encodeMixedRouteToPath(route_0_V3_1)).toEqual( @@ -172,7 +184,7 @@ describe('#encodeMixedRouteToPath', () => { it('packs them for exact input native eth v4 -> v3', () => { expect(encodeMixedRouteToPath(route_eth_V4_0_V3_1)).toEqual( - '0x0000000000000000000000000000000000000000400bb800001e00000000000000000000000000000000000000000000000000000000000000000000000000000001300bb80000000000000000000000000000000000000002' + '0x0000000000000000000000000000000000000000 400bb800001e00000000000000000000000000000000000000000000000000000000000000000000000000000001300bb80000000000000000000000000000000000000002' ) }) @@ -181,5 +193,29 @@ describe('#encodeMixedRouteToPath', () => { '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2300bb80000000000000000000000000000000000000001400bb800001e00000000000000000000000000000000000000000000000000000000000000000000000000000002' ) }) + + it('encodes the mixed route with an unwrap, token1 v2 -> v4 token0 through an unwrap', () => { + expect(encodeMixedRouteToPath(route_1_v2_weth_v0_eth_v4_token0)).toEqual('0x000000000000000000000000000000000000000220c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000400bb800001e00000000000000000000000000000000000000000000000000000000000000000000000000000001') + // comments left for future reference, to show special cased eth-weth v4 (version0) encoding in the mixed route quoter + // // first path address - token1 + // 0x0000000000000000000000000000000000000002 + // // first path fee - v2 "version" + // 0x20 + // // first path second address - weth + // 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 + // // second path - fake v4 pool, "version" + // 0x00 + // // second path - fake v4 pool, second address - eth + // 0x0000000000000000000000000000000000000000 + // // last path - v4 pool, with Fee.MEDIUM + // 0x400bb8 + // // last path - v4, tick spacing of 30 + // 0x00001e + // // last path - v4, hook address + // 0x0000000000000000000000000000000000000000 + // // last path address - v4 pool, token0 + // 0x0000000000000000000000000000000000000001 + + }) }) }) From 6f062949fa1681454842230938c4d15661bf1ed5 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Fri, 31 Jan 2025 00:36:10 -0500 Subject: [PATCH 5/7] fix linting, undo unrelated test change --- .../src/utils/encodeMixedRouteToPath.test.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sdks/router-sdk/src/utils/encodeMixedRouteToPath.test.ts b/sdks/router-sdk/src/utils/encodeMixedRouteToPath.test.ts index 19ad24ea1..a409ae009 100644 --- a/sdks/router-sdk/src/utils/encodeMixedRouteToPath.test.ts +++ b/sdks/router-sdk/src/utils/encodeMixedRouteToPath.test.ts @@ -71,7 +71,11 @@ describe('#encodeMixedRouteToPath', () => { const route_eth_V4_0_V3_1 = new MixedRouteSDK([pool_V4_0_eth, pool_V3_0_1_medium], ETHER, token1) const route_eth_V3_0_V4_1 = new MixedRouteSDK([pool_V3_0_weth, pool_V4_0_1], ETHER, token1) - const route_1_v2_weth_v0_eth_v4_token0 = new MixedRouteSDK([pair_1_weth, fake_v4_eth_weth_pool, pool_V4_0_eth], token1, token0) + const route_1_v2_weth_v0_eth_v4_token0 = new MixedRouteSDK( + [pair_1_weth, fake_v4_eth_weth_pool, pool_V4_0_eth], + token1, + token0 + ) describe('pure V3', () => { it('packs them for exact input single hop', () => { @@ -184,7 +188,7 @@ describe('#encodeMixedRouteToPath', () => { it('packs them for exact input native eth v4 -> v3', () => { expect(encodeMixedRouteToPath(route_eth_V4_0_V3_1)).toEqual( - '0x0000000000000000000000000000000000000000 400bb800001e00000000000000000000000000000000000000000000000000000000000000000000000000000001300bb80000000000000000000000000000000000000002' + '0x0000000000000000000000000000000000000000400bb800001e00000000000000000000000000000000000000000000000000000000000000000000000000000001300bb80000000000000000000000000000000000000002' ) }) @@ -195,7 +199,9 @@ describe('#encodeMixedRouteToPath', () => { }) it('encodes the mixed route with an unwrap, token1 v2 -> v4 token0 through an unwrap', () => { - expect(encodeMixedRouteToPath(route_1_v2_weth_v0_eth_v4_token0)).toEqual('0x000000000000000000000000000000000000000220c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000400bb800001e00000000000000000000000000000000000000000000000000000000000000000000000000000001') + expect(encodeMixedRouteToPath(route_1_v2_weth_v0_eth_v4_token0)).toEqual( + '0x000000000000000000000000000000000000000220c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000400bb800001e00000000000000000000000000000000000000000000000000000000000000000000000000000001' + ) // comments left for future reference, to show special cased eth-weth v4 (version0) encoding in the mixed route quoter // // first path address - token1 // 0x0000000000000000000000000000000000000002 @@ -215,7 +221,6 @@ describe('#encodeMixedRouteToPath', () => { // 0x0000000000000000000000000000000000000000 // // last path address - v4 pool, token0 // 0x0000000000000000000000000000000000000001 - }) }) }) From fa009cf61120630ef86a26f85c44a50503953d08 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Fri, 31 Jan 2025 09:50:21 -0500 Subject: [PATCH 6/7] bump v4-sdk --- sdks/router-sdk/package.json | 2 +- yarn.lock | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/sdks/router-sdk/package.json b/sdks/router-sdk/package.json index 451dd9934..d2bdaa31b 100644 --- a/sdks/router-sdk/package.json +++ b/sdks/router-sdk/package.json @@ -25,7 +25,7 @@ "@uniswap/swap-router-contracts": "^1.3.0", "@uniswap/v2-sdk": "^4.13.0", "@uniswap/v3-sdk": "^3.24.0", - "@uniswap/v4-sdk": "^1.18.0" + "@uniswap/v4-sdk": "^1.18.1" }, "devDependencies": { "@types/jest": "^24.0.25", diff --git a/yarn.lock b/yarn.lock index 2dd2f9e45..cca6eccac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4533,7 +4533,7 @@ __metadata: "@uniswap/swap-router-contracts": ^1.3.0 "@uniswap/v2-sdk": ^4.13.0 "@uniswap/v3-sdk": ^3.24.0 - "@uniswap/v4-sdk": ^1.18.0 + "@uniswap/v4-sdk": ^1.18.1 prettier: ^2.4.1 tsdx: ^0.14.1 languageName: unknown @@ -4804,6 +4804,19 @@ __metadata: languageName: node linkType: hard +"@uniswap/v4-sdk@npm:^1.18.1": + version: 1.18.1 + resolution: "@uniswap/v4-sdk@npm:1.18.1" + dependencies: + "@ethersproject/solidity": ^5.0.9 + "@uniswap/sdk-core": ^7.5.0 + "@uniswap/v3-sdk": 3.24.0 + tiny-invariant: ^1.1.0 + tiny-warning: ^1.0.3 + checksum: b107e7afec5f9422472bb0752a117b17f98b2671a6824a216d557e8d179ce2af9eacd21c8591b7f946f0f4cf933e2adda6d4dfd3747067576fb16435714dde0c + languageName: node + linkType: hard + "@uniswap/v4-sdk@workspace:sdks/v4-sdk": version: 0.0.0-use.local resolution: "@uniswap/v4-sdk@workspace:sdks/v4-sdk" From 7d9082544b84eb94a827302e92acc60b06d7c4ef Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Fri, 31 Jan 2025 09:53:14 -0500 Subject: [PATCH 7/7] dedupe --- yarn.lock | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/yarn.lock b/yarn.lock index cca6eccac..3328e3e3e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4791,20 +4791,7 @@ __metadata: languageName: node linkType: hard -"@uniswap/v4-sdk@npm:^1.18.0": - version: 1.18.0 - resolution: "@uniswap/v4-sdk@npm:1.18.0" - dependencies: - "@ethersproject/solidity": ^5.0.9 - "@uniswap/sdk-core": ^7.5.0 - "@uniswap/v3-sdk": 3.24.0 - tiny-invariant: ^1.1.0 - tiny-warning: ^1.0.3 - checksum: 37d2ebd3781eb9d5f5e0e875d7788d2369720fd30a53dba9abb7bb8df97eb89ddad2baab99c99aab566b350e1efbfe4e0d26765a9a49da38aaab767be05eafb8 - languageName: node - linkType: hard - -"@uniswap/v4-sdk@npm:^1.18.1": +"@uniswap/v4-sdk@npm:^1.18.0, @uniswap/v4-sdk@npm:^1.18.1": version: 1.18.1 resolution: "@uniswap/v4-sdk@npm:1.18.1" dependencies: