diff --git a/lib/entities/context/DutchQuoteContext.ts b/lib/entities/context/DutchQuoteContext.ts index f95f1966..9614bfdd 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,11 @@ 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 - : 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, 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..d5e0b889 100644 --- a/lib/fetchers/Permit2Fetcher.ts +++ b/lib/fetchers/Permit2Fetcher.ts @@ -1,22 +1,33 @@ -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'; +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 permit2Address: string; public readonly permit2Abi: ethers.ContractInterface; - private readonly permit2: ethers.Contract; + private readonly chainIdPermit2Map: Map; 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); + 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 { + return permit2Address(chainId); } public async fetchAllowance( @@ -31,7 +42,9 @@ 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 = 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); } catch (e) { diff --git a/lib/util/permit2.ts b/lib/util/permit2.ts index e4a5a4ac..f9dd5ead 100644 --- a/lib/util/permit2.ts +++ b/lib/util/permit2.ts @@ -1,4 +1,4 @@ -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 +22,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); });