From 459b754845f977e95bb9d76adf2d225828b71420 Mon Sep 17 00:00:00 2001 From: Vasyl Ivanchuk Date: Fri, 24 May 2024 14:24:11 +0300 Subject: [PATCH] fix: explorer doesn't require defined bridge address --- .../src/blockchain/blockchain.service.spec.ts | 38 ++++++++----- .../src/blockchain/blockchain.service.ts | 6 +- .../src/token/token.service.spec.ts | 54 ++++++++++++++++++ .../src/transfer/transfer.service.spec.ts | 14 +---- .../src/blockchain/blockchain.service.spec.ts | 38 ++++++++----- .../src/blockchain/blockchain.service.ts | 6 +- .../worker/src/token/token.service.spec.ts | 56 +++++++++++++++++++ 7 files changed, 165 insertions(+), 47 deletions(-) diff --git a/packages/data-fetcher/src/blockchain/blockchain.service.spec.ts b/packages/data-fetcher/src/blockchain/blockchain.service.spec.ts index 2e2a1f4b12..a496fd4dcd 100644 --- a/packages/data-fetcher/src/blockchain/blockchain.service.spec.ts +++ b/packages/data-fetcher/src/blockchain/blockchain.service.spec.ts @@ -2362,23 +2362,35 @@ describe("BlockchainService", () => { describe("onModuleInit", () => { let bridgeAddresses; - beforeEach(() => { - bridgeAddresses = { - erc20L1: "l1Erc20DefaultBridge", - erc20L2: "l2Erc20DefaultBridge", - }; - jest.spyOn(provider, "getDefaultBridgeAddresses").mockResolvedValueOnce(bridgeAddresses); - }); + describe("when l2 ERC20 default bridge is defined", () => { + beforeEach(() => { + bridgeAddresses = { + erc20L2: "l2Erc20DefaultBridge", + }; - it("inits L2 ERC20 bridge address", async () => { - await blockchainService.onModuleInit(); - expect(blockchainService.bridgeAddresses.l2Erc20DefaultBridge).toBe(bridgeAddresses.erc20L2.toLowerCase()); + jest.spyOn(provider, "getDefaultBridgeAddresses").mockResolvedValueOnce(bridgeAddresses); + }); + + it("inits L2 ERC20 bridge address", async () => { + await blockchainService.onModuleInit(); + expect(blockchainService.bridgeAddresses.l2Erc20DefaultBridge).toBe(bridgeAddresses.erc20L2.toLowerCase()); + }); }); - it("inits L1 ERC20 bridge address", async () => { - await blockchainService.onModuleInit(); - expect(blockchainService.bridgeAddresses.l1Erc20DefaultBridge).toBe(bridgeAddresses.erc20L1.toLowerCase()); + describe("when l2 ERC20 default bridge is not defined", () => { + beforeEach(() => { + bridgeAddresses = { + erc20L2: null, + }; + + jest.spyOn(provider, "getDefaultBridgeAddresses").mockResolvedValueOnce(bridgeAddresses); + }); + + it("sets L2 ERC20 bridge address to null", async () => { + await blockchainService.onModuleInit(); + expect(blockchainService.bridgeAddresses.l2Erc20DefaultBridge).toBe(undefined); + }); }); }); }); diff --git a/packages/data-fetcher/src/blockchain/blockchain.service.ts b/packages/data-fetcher/src/blockchain/blockchain.service.ts index 4b3cd8d8d3..16825128da 100644 --- a/packages/data-fetcher/src/blockchain/blockchain.service.ts +++ b/packages/data-fetcher/src/blockchain/blockchain.service.ts @@ -11,8 +11,7 @@ import { BLOCKCHAIN_RPC_CALL_DURATION_METRIC_NAME, BlockchainRpcCallMetricLabel import { RetryableContract } from "./retryableContract"; export interface BridgeAddresses { - l1Erc20DefaultBridge: string; - l2Erc20DefaultBridge: string; + l2Erc20DefaultBridge?: string; } export interface TraceTransactionResult { @@ -184,8 +183,7 @@ export class BlockchainService implements OnModuleInit { const bridgeAddresses = await this.getDefaultBridgeAddresses(); this.bridgeAddresses = { - l1Erc20DefaultBridge: bridgeAddresses.erc20L1.toLowerCase(), - l2Erc20DefaultBridge: bridgeAddresses.erc20L2.toLowerCase(), + l2Erc20DefaultBridge: bridgeAddresses.erc20L2?.toLowerCase(), }; this.logger.debug(`L2 ERC20 Bridge is set to: ${this.bridgeAddresses.l2Erc20DefaultBridge}`); diff --git a/packages/data-fetcher/src/token/token.service.spec.ts b/packages/data-fetcher/src/token/token.service.spec.ts index 499c04b606..075f0f84e9 100644 --- a/packages/data-fetcher/src/token/token.service.spec.ts +++ b/packages/data-fetcher/src/token/token.service.spec.ts @@ -401,6 +401,60 @@ describe("TokenService", () => { }); }); + describe("when there is a bridge initialize log in transaction receipt but the default bridge contract is not defined", () => { + beforeEach(() => { + blockchainServiceMock.bridgeAddresses.l2Erc20DefaultBridge = undefined; + transactionReceipt.to = "0x0000000000000000000000000000000000001112"; + transactionReceipt.logs = [ + mock({ + topics: [ + "0x290afdae231a3fc0bbae8b1af63698b0a1d79b21ad17df0342dfb952fe74f8e5", + "0x000000000000000000000000913389f49358cb49a8e9e984a5871df43f80eb96", + "0x01000125c745537b5254be2ca086aee7fbd5d91789ed15790a942f9422d36447", + "0x0000000000000000000000005a393c95e7bddd0281650023d8c746fb1f596b7b", + ], + }), + mock({ + address: "0x5a393c95e7Bddd0281650023D8C746fB1F596B7b", + topics: [ + "0x81e8e92e5873539605a102eddae7ed06d19bea042099a437cbc3644415eb7404", + "0x000000000000000000000000c8f8ce6491227a6a2ab92e67a64011a4eba1c6cf", + ], + data: "0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000134c313131206465706c6f79656420746f204c310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044c31313100000000000000000000000000000000000000000000000000000000", + }), + ]; + + deployedContractAddress = mock({ + address: "0x5a393c95e7bddd0281650023d8c746fb1f596b7b", + blockNumber: 10, + transactionHash: "transactionHash", + logIndex: 20, + }); + }); + + it("starts the get token info duration metric", async () => { + await tokenService.getERC20Token(deployedContractAddress, transactionReceipt); + expect(startGetTokenInfoDurationMetricMock).toHaveBeenCalledTimes(1); + }); + + it("gets token data by the contract address", async () => { + await tokenService.getERC20Token(deployedContractAddress, transactionReceipt); + expect(blockchainServiceMock.getERC20TokenData).toHaveBeenCalledTimes(1); + expect(blockchainServiceMock.getERC20TokenData).toHaveBeenCalledWith(deployedContractAddress.address); + }); + + it("returns the token without l1Address", async () => { + const token = await tokenService.getERC20Token(deployedContractAddress, transactionReceipt); + expect(token).toStrictEqual({ + ...tokenData, + blockNumber: deployedContractAddress.blockNumber, + transactionHash: deployedContractAddress.transactionHash, + l2Address: deployedContractAddress.address, + logIndex: deployedContractAddress.logIndex, + }); + }); + }); + describe("if the token symbol or name has special symbols", () => { beforeEach(() => { jest.spyOn(blockchainServiceMock, "getERC20TokenData").mockResolvedValueOnce({ diff --git a/packages/data-fetcher/src/transfer/transfer.service.spec.ts b/packages/data-fetcher/src/transfer/transfer.service.spec.ts index f1beeab6e2..a2f4e22996 100644 --- a/packages/data-fetcher/src/transfer/transfer.service.spec.ts +++ b/packages/data-fetcher/src/transfer/transfer.service.spec.ts @@ -4,7 +4,6 @@ import { mock } from "jest-mock-extended"; import { BigNumber } from "ethers"; import { types } from "zksync-web3"; import { TransferService } from "./transfer.service"; -import { BlockchainService } from "../blockchain/blockchain.service"; import { TokenType } from "../token/token.service"; import * as ethDepositNoFee from "../../test/transactionReceipts/eth/deposit-no-fee.json"; @@ -68,18 +67,7 @@ describe("TransferService", () => { beforeEach(async () => { const app = await Test.createTestingModule({ - providers: [ - TransferService, - { - provide: BlockchainService, - useValue: { - bridgeAddresses: { - l1Erc20DefaultBridge: "0xc0543dab6ac5d3e3ff2e5a5e39e15186d0306808", - l2Erc20DefaultBridge: "0xc7e0220d02d549c4846a6ec31d89c3b670ebe35c", - }, - }, - }, - ], + providers: [TransferService], }).compile(); app.useLogger(mock()); diff --git a/packages/worker/src/blockchain/blockchain.service.spec.ts b/packages/worker/src/blockchain/blockchain.service.spec.ts index bacfa748b1..e545d92b54 100644 --- a/packages/worker/src/blockchain/blockchain.service.spec.ts +++ b/packages/worker/src/blockchain/blockchain.service.spec.ts @@ -1613,23 +1613,35 @@ describe("BlockchainService", () => { describe("onModuleInit", () => { let bridgeAddresses; - beforeEach(() => { - bridgeAddresses = { - erc20L1: "l1Erc20DefaultBridge", - erc20L2: "l2Erc20DefaultBridge", - }; - jest.spyOn(provider, "getDefaultBridgeAddresses").mockResolvedValueOnce(bridgeAddresses); - }); + describe("when l2 ERC20 default bridge is defined", () => { + beforeEach(() => { + bridgeAddresses = { + erc20L2: "l2Erc20DefaultBridge", + }; - it("inits L2 ERC20 bridge address", async () => { - await blockchainService.onModuleInit(); - expect(blockchainService.bridgeAddresses.l2Erc20DefaultBridge).toBe(bridgeAddresses.erc20L2.toLowerCase()); + jest.spyOn(provider, "getDefaultBridgeAddresses").mockResolvedValueOnce(bridgeAddresses); + }); + + it("inits L2 ERC20 bridge address", async () => { + await blockchainService.onModuleInit(); + expect(blockchainService.bridgeAddresses.l2Erc20DefaultBridge).toBe(bridgeAddresses.erc20L2.toLowerCase()); + }); }); - it("inits L1 ERC20 bridge address", async () => { - await blockchainService.onModuleInit(); - expect(blockchainService.bridgeAddresses.l1Erc20DefaultBridge).toBe(bridgeAddresses.erc20L1.toLowerCase()); + describe("when l2 ERC20 default bridge is not defined", () => { + beforeEach(() => { + bridgeAddresses = { + erc20L2: null, + }; + + jest.spyOn(provider, "getDefaultBridgeAddresses").mockResolvedValueOnce(bridgeAddresses); + }); + + it("sets L2 ERC20 bridge address to null", async () => { + await blockchainService.onModuleInit(); + expect(blockchainService.bridgeAddresses.l2Erc20DefaultBridge).toBe(undefined); + }); }); }); }); diff --git a/packages/worker/src/blockchain/blockchain.service.ts b/packages/worker/src/blockchain/blockchain.service.ts index 741631c8d5..06108ce16b 100644 --- a/packages/worker/src/blockchain/blockchain.service.ts +++ b/packages/worker/src/blockchain/blockchain.service.ts @@ -11,8 +11,7 @@ import { BLOCKCHAIN_RPC_CALL_DURATION_METRIC_NAME, BlockchainRpcCallMetricLabel import { RetryableContract } from "./retryableContract"; export interface BridgeAddresses { - l1Erc20DefaultBridge: string; - l2Erc20DefaultBridge: string; + l2Erc20DefaultBridge?: string; } export interface TraceTransactionResult { @@ -176,8 +175,7 @@ export class BlockchainService implements OnModuleInit { const bridgeAddresses = await this.getDefaultBridgeAddresses(); this.bridgeAddresses = { - l1Erc20DefaultBridge: bridgeAddresses.erc20L1.toLowerCase(), - l2Erc20DefaultBridge: bridgeAddresses.erc20L2.toLowerCase(), + l2Erc20DefaultBridge: bridgeAddresses.erc20L2?.toLowerCase(), }; this.logger.debug(`L2 ERC20 Bridge is set to: ${this.bridgeAddresses.l2Erc20DefaultBridge}`); diff --git a/packages/worker/src/token/token.service.spec.ts b/packages/worker/src/token/token.service.spec.ts index f277e79832..8423a5396b 100644 --- a/packages/worker/src/token/token.service.spec.ts +++ b/packages/worker/src/token/token.service.spec.ts @@ -427,6 +427,62 @@ describe("TokenService", () => { }); }); + describe("when there is a bridge initialize log in transaction receipt but the default bridge contract is not defined", () => { + beforeEach(() => { + blockchainServiceMock.bridgeAddresses.l2Erc20DefaultBridge = undefined; + transactionReceipt.to = "0x0000000000000000000000000000000000001112"; + transactionReceipt.logs = [ + mock({ + topics: [ + "0x290afdae231a3fc0bbae8b1af63698b0a1d79b21ad17df0342dfb952fe74f8e5", + "0x000000000000000000000000913389f49358cb49a8e9e984a5871df43f80eb96", + "0x01000125c745537b5254be2ca086aee7fbd5d91789ed15790a942f9422d36447", + "0x0000000000000000000000005a393c95e7bddd0281650023d8c746fb1f596b7b", + ], + }), + mock({ + address: "0x5a393c95e7Bddd0281650023D8C746fB1F596B7b", + topics: [ + "0x81e8e92e5873539605a102eddae7ed06d19bea042099a437cbc3644415eb7404", + "0x000000000000000000000000c8f8ce6491227a6a2ab92e67a64011a4eba1c6cf", + ], + data: "0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000134c313131206465706c6f79656420746f204c310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044c31313100000000000000000000000000000000000000000000000000000000", + }), + ]; + + deployedContractAddress = mock({ + address: "0x5a393c95e7bddd0281650023d8c746fb1f596b7b", + blockNumber: 10, + transactionHash: "transactionHash", + logIndex: 20, + }); + }); + + it("starts the get token info duration metric", async () => { + await tokenService.saveERC20Token(deployedContractAddress, transactionReceipt); + expect(startGetTokenInfoDurationMetricMock).toHaveBeenCalledTimes(1); + }); + + it("gets token data by the contract address", async () => { + await tokenService.saveERC20Token(deployedContractAddress, transactionReceipt); + expect(blockchainServiceMock.getERC20TokenData).toHaveBeenCalledTimes(1); + expect(blockchainServiceMock.getERC20TokenData).toHaveBeenCalledWith(deployedContractAddress.address); + }); + + it("upserts the token without l1Address", async () => { + await tokenService.saveERC20Token(deployedContractAddress, transactionReceipt); + expect(tokenRepositoryMock.upsert).toHaveBeenCalledTimes(1); + expect(tokenRepositoryMock.upsert).toHaveBeenCalledWith({ + ...tokenData, + blockNumber: deployedContractAddress.blockNumber, + transactionHash: deployedContractAddress.transactionHash, + l2Address: deployedContractAddress.address, + l1Address: undefined, + logIndex: deployedContractAddress.logIndex, + }); + }); + }); + describe("if the token symbol is empty", () => { beforeEach(() => { jest.spyOn(blockchainServiceMock, "getERC20TokenData").mockResolvedValueOnce({