From 6f59f73e6f615000a55b22ff2b723ed344c6b524 Mon Sep 17 00:00:00 2001 From: Siyu Jiang <91580504+jsy1218@users.noreply.github.com> Date: Tue, 11 Jun 2024 13:14:29 -0700 Subject: [PATCH 1/3] fix: permit2 address different on zksync --- lib/entities/context/DutchQuoteContext.ts | 7 ++++--- lib/fetchers/Permit2Fetcher.ts | 15 ++++++++++----- lib/util/permit2.ts | 9 +++++++-- test/unit/lib/fetchers/Permit2Fetcher.test.ts | 4 ++-- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/lib/entities/context/DutchQuoteContext.ts b/lib/entities/context/DutchQuoteContext.ts index f95f1966..6a32d405 100644 --- a/lib/entities/context/DutchQuoteContext.ts +++ b/lib/entities/context/DutchQuoteContext.ts @@ -1,5 +1,5 @@ import DEFAULT_TOKEN_LIST from '@uniswap/default-token-list'; -import { PERMIT2_ADDRESS } from '@uniswap/permit2-sdk'; +import { permit2Address } from '@uniswap/permit2-sdk'; import { Protocol } from '@uniswap/router-sdk'; import { ChainId, TradeType } from '@uniswap/sdk-core'; @@ -271,12 +271,13 @@ export class DutchQuoteContext implements QuoteContext { // either swapper was not set or is zero address if (!request.info.swapper || request.info.swapper == NATIVE_ADDRESS) return false; + const chainId = request.info.tokenInChainId as ChainId const tokenInAddress = request.info.tokenIn == NATIVE_ADDRESS - ? WRAPPED_NATIVE_CURRENCY[request.info.tokenInChainId as ChainId].address + ? WRAPPED_NATIVE_CURRENCY[chainId].address : request.info.tokenIn; const tokenContract = Erc20__factory.connect(tokenInAddress, this.rpcProvider); - const permit2Allowance = await tokenContract.allowance(request.info.swapper, PERMIT2_ADDRESS); + const permit2Allowance = await tokenContract.allowance(request.info.swapper, permit2Address(chainId)); if (request.info.type == TradeType.EXACT_OUTPUT) { // If exactOutput, we don't know how much tokenIn will be needed diff --git a/lib/fetchers/Permit2Fetcher.ts b/lib/fetchers/Permit2Fetcher.ts index 4406c9af..5a05c93a 100644 --- a/lib/fetchers/Permit2Fetcher.ts +++ b/lib/fetchers/Permit2Fetcher.ts @@ -1,4 +1,4 @@ -import { PERMIT2_ADDRESS, PermitDetails } from '@uniswap/permit2-sdk'; +import { permit2Address, PermitDetails } from '@uniswap/permit2-sdk'; import { ChainId } from '@uniswap/sdk-core'; import { Unit } from 'aws-embedded-metrics'; import { ethers, providers } from 'ethers'; @@ -7,16 +7,20 @@ import { log } from '../util/log'; import { metrics } from '../util/metrics'; export class Permit2Fetcher { - public readonly permit2Address: string; public readonly permit2Abi: ethers.ContractInterface; private readonly permit2: ethers.Contract; + private readonly permit2ZkSync: ethers.Contract; private readonly chainIdRpcMap: Map; constructor(chainIdRpcMap: Map) { this.chainIdRpcMap = chainIdRpcMap; - this.permit2Address = PERMIT2_ADDRESS; this.permit2Abi = PERMIT2_CONTRACT.abi; - this.permit2 = new ethers.Contract(this.permit2Address, this.permit2Abi); + this.permit2 = new ethers.Contract(permit2Address(), this.permit2Abi); + this.permit2ZkSync = new ethers.Contract(permit2Address(ChainId.ZKSYNC), this.permit2Abi); + } + + public permit2Address(chainId: ChainId): string { + return permit2Address(chainId); } public async fetchAllowance( @@ -31,7 +35,8 @@ export class Permit2Fetcher { const beforePermitCheck = Date.now(); const rpcProvider = this.chainIdRpcMap.get(chainId); if (!rpcProvider) throw new Error(`No rpc provider found for chain: ${chainId}`); - allowance = await this.permit2.connect(rpcProvider).allowance(ownerAddress, tokenAddress, spenderAddress); + const permit2 = chainId === ChainId.ZKSYNC ? this.permit2ZkSync : this.permit2; + allowance = await permit2.connect(rpcProvider).allowance(ownerAddress, tokenAddress, spenderAddress); metrics.putMetric(`Permit2FetcherSuccess`, 1); metrics.putMetric(`Latency-Permit2Fetcher-ChainId${chainId}`, Date.now() - beforePermitCheck, Unit.Milliseconds); } catch (e) { diff --git a/lib/util/permit2.ts b/lib/util/permit2.ts index e4a5a4ac..9d09282a 100644 --- a/lib/util/permit2.ts +++ b/lib/util/permit2.ts @@ -1,4 +1,9 @@ -import { AllowanceTransfer, MaxAllowanceTransferAmount, PERMIT2_ADDRESS, PermitSingleData } from '@uniswap/permit2-sdk'; +import { + AllowanceTransfer, + MaxAllowanceTransferAmount, + permit2Address, + PermitSingleData +} from '@uniswap/permit2-sdk'; import { UNIVERSAL_ROUTER_ADDRESS } from '@uniswap/universal-router-sdk'; import ms from 'ms'; @@ -22,5 +27,5 @@ export function createPermitData(tokenAddress: string, chainId: number, nonce: s sigDeadline: toDeadline(PERMIT_SIG_EXPIRATION).toString(), }; - return AllowanceTransfer.getPermitData(permit, PERMIT2_ADDRESS, chainId) as PermitSingleData; + return AllowanceTransfer.getPermitData(permit, permit2Address(chainId), chainId) as PermitSingleData; } diff --git a/test/unit/lib/fetchers/Permit2Fetcher.test.ts b/test/unit/lib/fetchers/Permit2Fetcher.test.ts index 7d9121ae..4ead7895 100644 --- a/test/unit/lib/fetchers/Permit2Fetcher.test.ts +++ b/test/unit/lib/fetchers/Permit2Fetcher.test.ts @@ -1,4 +1,4 @@ -import { PERMIT2_ADDRESS } from '@uniswap/permit2-sdk'; +import { permit2Address } from '@uniswap/permit2-sdk'; import { ChainId } from '@uniswap/sdk-core'; import PERMIT2_CONTRACT from '../../../../lib/abis/Permit2.json'; import { Permit2Fetcher } from '../../../../lib/fetchers/Permit2Fetcher'; @@ -9,7 +9,7 @@ describe('Permit2Fetcher Unit Tests', () => { const rpcUrlMap = new Map(); rpcUrlMap.set(ChainId.MAINNET, 'mainnet rpc url'); const fetcher = new Permit2Fetcher(rpcUrlMap); - expect(fetcher.permit2Address).toBe(PERMIT2_ADDRESS); + expect(fetcher.permit2Address(ChainId.MAINNET)).toBe(permit2Address(ChainId.MAINNET)); expect(fetcher.permit2Abi).toBe(PERMIT2_CONTRACT.abi); }); From 49530d1c1f83e1faf9eb50b389f8c4156b173354 Mon Sep 17 00:00:00 2001 From: Siyu Jiang <91580504+jsy1218@users.noreply.github.com> Date: Tue, 11 Jun 2024 13:16:33 -0700 Subject: [PATCH 2/3] fix prettier --- lib/entities/context/DutchQuoteContext.ts | 6 ++---- lib/util/permit2.ts | 7 +------ 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/lib/entities/context/DutchQuoteContext.ts b/lib/entities/context/DutchQuoteContext.ts index 6a32d405..9614bfdd 100644 --- a/lib/entities/context/DutchQuoteContext.ts +++ b/lib/entities/context/DutchQuoteContext.ts @@ -271,11 +271,9 @@ export class DutchQuoteContext implements QuoteContext { // either swapper was not set or is zero address if (!request.info.swapper || request.info.swapper == NATIVE_ADDRESS) return false; - const chainId = request.info.tokenInChainId as ChainId + const chainId = request.info.tokenInChainId as ChainId; const tokenInAddress = - request.info.tokenIn == NATIVE_ADDRESS - ? WRAPPED_NATIVE_CURRENCY[chainId].address - : request.info.tokenIn; + request.info.tokenIn == NATIVE_ADDRESS ? WRAPPED_NATIVE_CURRENCY[chainId].address : request.info.tokenIn; const tokenContract = Erc20__factory.connect(tokenInAddress, this.rpcProvider); const permit2Allowance = await tokenContract.allowance(request.info.swapper, permit2Address(chainId)); diff --git a/lib/util/permit2.ts b/lib/util/permit2.ts index 9d09282a..f9dd5ead 100644 --- a/lib/util/permit2.ts +++ b/lib/util/permit2.ts @@ -1,9 +1,4 @@ -import { - AllowanceTransfer, - MaxAllowanceTransferAmount, - permit2Address, - PermitSingleData -} from '@uniswap/permit2-sdk'; +import { AllowanceTransfer, MaxAllowanceTransferAmount, permit2Address, PermitSingleData } from '@uniswap/permit2-sdk'; import { UNIVERSAL_ROUTER_ADDRESS } from '@uniswap/universal-router-sdk'; import ms from 'ms'; From 4d61b82b247a8f7996363d4cd1e4e702cd45c68a Mon Sep 17 00:00:00 2001 From: Siyu Jiang <91580504+jsy1218@users.noreply.github.com> Date: Wed, 12 Jun 2024 09:15:27 -0700 Subject: [PATCH 3/3] feedback --- lib/fetchers/Permit2Fetcher.ts | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/lib/fetchers/Permit2Fetcher.ts b/lib/fetchers/Permit2Fetcher.ts index 5a05c93a..d5e0b889 100644 --- a/lib/fetchers/Permit2Fetcher.ts +++ b/lib/fetchers/Permit2Fetcher.ts @@ -1,22 +1,29 @@ import { permit2Address, PermitDetails } from '@uniswap/permit2-sdk'; import { ChainId } from '@uniswap/sdk-core'; import { Unit } from 'aws-embedded-metrics'; -import { ethers, providers } from 'ethers'; +import { Contract, ethers, providers } from 'ethers'; import PERMIT2_CONTRACT from '../abis/Permit2.json'; import { log } from '../util/log'; import { metrics } from '../util/metrics'; export class Permit2Fetcher { public readonly permit2Abi: ethers.ContractInterface; - private readonly permit2: ethers.Contract; - private readonly permit2ZkSync: ethers.Contract; + private readonly chainIdPermit2Map: Map; private readonly chainIdRpcMap: Map; constructor(chainIdRpcMap: Map) { this.chainIdRpcMap = chainIdRpcMap; this.permit2Abi = PERMIT2_CONTRACT.abi; - this.permit2 = new ethers.Contract(permit2Address(), this.permit2Abi); - this.permit2ZkSync = new ethers.Contract(permit2Address(ChainId.ZKSYNC), this.permit2Abi); + const permit2 = new ethers.Contract(permit2Address(), this.permit2Abi); + const permit2ZkSync = new ethers.Contract(permit2Address(ChainId.ZKSYNC), this.permit2Abi); + this.chainIdPermit2Map = new Map(); + this.chainIdRpcMap.forEach((_, chainId) => { + if (chainId === ChainId.ZKSYNC) { + this.chainIdPermit2Map.set(chainId, permit2ZkSync); + } else { + this.chainIdPermit2Map.set(chainId, permit2); + } + }); } public permit2Address(chainId: ChainId): string { @@ -35,7 +42,8 @@ export class Permit2Fetcher { const beforePermitCheck = Date.now(); const rpcProvider = this.chainIdRpcMap.get(chainId); if (!rpcProvider) throw new Error(`No rpc provider found for chain: ${chainId}`); - const permit2 = chainId === ChainId.ZKSYNC ? this.permit2ZkSync : this.permit2; + const permit2 = this.chainIdPermit2Map.get(chainId); + if (!permit2) throw new Error(`No permit2 contract found for chain: ${chainId}`); allowance = await permit2.connect(rpcProvider).allowance(ownerAddress, tokenAddress, spenderAddress); metrics.putMetric(`Permit2FetcherSuccess`, 1); metrics.putMetric(`Latency-Permit2Fetcher-ChainId${chainId}`, Date.now() - beforePermitCheck, Unit.Milliseconds);