From 7241688a14098156bdb880aa974402d27bb8bf89 Mon Sep 17 00:00:00 2001 From: Christophe Date: Tue, 2 Jul 2024 14:03:52 +0000 Subject: [PATCH 01/11] Feat: Add `getUpgradeExecutor` function Closes FS-627 --- src/getUpgradeExecutor.ts | 58 +++++++++++++++++++ src/getUpgradeExecutor.unit.test.ts | 87 +++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 src/getUpgradeExecutor.ts create mode 100644 src/getUpgradeExecutor.unit.test.ts diff --git a/src/getUpgradeExecutor.ts b/src/getUpgradeExecutor.ts new file mode 100644 index 00000000..744f4396 --- /dev/null +++ b/src/getUpgradeExecutor.ts @@ -0,0 +1,58 @@ +import { Address, Chain, PublicClient, Transport, getAbiItem } from 'viem'; +import { rollupAdminLogicABI } from './abi'; +import { createRollupFetchTransactionHash } from './createRollupFetchTransactionHash'; + +const AdminChangedAbi = getAbiItem({ abi: rollupAdminLogicABI, name: 'AdminChanged' }); + +export type GetUpgradeExecutorParams = { + /** Address of the rollup we're getting logs from */ + rollup: Address; +}; +/** + * Address of the current upgrade executor + */ +export type GetUpgradeExecutorReturnType = Address | undefined; + +/** + * + * @param {PublicClient} publicClient - The chain Viem Public Client + * @param {GetUpgradeExecutorParams} GetUpgradeExecutorParams {@link GetUpgradeExecutorParams} + * + * @returns Promise<{@link GetUpgradeExecutorReturnType}> + * + * @example + * const upgradeExecutor = getUpgradeExecutor(client, { + * rollup: '0xc47dacfbaa80bd9d8112f4e8069482c2a3221336' + * }); + * + */ +export async function getUpgradeExecutor( + publicClient: PublicClient, + { rollup }: GetUpgradeExecutorParams, +): Promise { + let blockNumber: bigint | 'earliest'; + let createRollupTransactionHash: Address | null = null; + + try { + createRollupTransactionHash = await createRollupFetchTransactionHash({ + rollup, + publicClient, + }); + const receipt = await publicClient.waitForTransactionReceipt({ + hash: createRollupTransactionHash, + }); + blockNumber = receipt.blockNumber; + } catch (e) { + console.warn(`[getUpgradeExecutor] ${(e as any).message}`); + blockNumber = 'earliest'; + } + + const events = await publicClient.getLogs({ + address: rollup, + events: [AdminChangedAbi], + fromBlock: blockNumber, + toBlock: 'latest', + }); + + return events[events.length - 1].args.newAdmin; +} diff --git a/src/getUpgradeExecutor.unit.test.ts b/src/getUpgradeExecutor.unit.test.ts new file mode 100644 index 00000000..2c7ebc0a --- /dev/null +++ b/src/getUpgradeExecutor.unit.test.ts @@ -0,0 +1,87 @@ +import { + Address, + EIP1193RequestFn, + createPublicClient, + createTransport, + http, + padHex, + zeroAddress, +} from 'viem'; +import { arbitrum, arbitrumSepolia } from 'viem/chains'; +import { it, expect, vi, describe } from 'vitest'; +import { getUpgradeExecutor } from './getUpgradeExecutor'; +import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; + +const client = createPublicClient({ + chain: arbitrum, + transport: http(), +}); + +const rollupAddress = '0xe0875cbd144fe66c015a95e5b2d2c15c3b612179'; + +function mockAdminChangedEvent(previousAdmin: Address, newAdmin: Address) { + return { + address: '0xa58f38102579dae7c584850780dda55744f67df1', + blockNumber: 183097536n, + transactionHash: '0x13baa9be2bf267fde01e730855d34526f339a21f1877af175f0958e5dc546e6d', + transactionIndex: 1, + blockHash: '0x31d403a11112e6a8be0e24423df83341790a8c1cc1728a2c2deff1b683961635', + logIndex: 0, + data: '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000013300000000000000010000000000000001012160184f37a4eaea75e8252d38d5b3f0298703794d58f38b3551104ce0c2472aea78f53ccd07fdb7b1c5b08444d2be9025d519ccc21d12fd9f8b67c50615694b626aaec898b9c1e613b0c17aac28539ee667a98e08d734193de9b2e612b4b082439506aa6ff965bfff2e8d3e6ade9e038412d767778850c717b388fb17e40c359c8ef3b99b4e7aee94b88f7d96c09e8d522a0f24d90efa7db34f42cefa18ae1ab1e08f780e613e0baf8e28c322a0d52b915fcff3e143a9daa7c2ba525029066f8230120e9803fd21d332015b3ec22ae180cbd1f3cf89561a0c5bd914dc5f746d692cefcb4762a012af0fe55c1148f138221a196fbec9942400b7772ce371c8ccc8ed0cd3926398cd62f1b900758b82591174295eb7ac00555d40051ad280ceb2cfa700000000000000000000000000', + args: { + previousAdmin, + newAdmin, + }, + eventName: 'AdminChanged', + }; +} + +function mockData({ logs, method }: { logs: unknown[]; method: 'eth_getLogs' }) { + if (method === 'eth_getLogs') { + return logs; + } + + return null; +} + +it('getUpgradeExecutor return current upgradeExecutor (Xai)', async () => { + const upgradeExecutor = await getUpgradeExecutor(client, { + rollup: '0xc47dacfbaa80bd9d8112f4e8069482c2a3221336', + }); + expect(upgradeExecutor).toEqual('0x0EE7AD3Cc291343C9952fFd8844e86d294fa513F'); +}); + +describe('AdminChanged', () => { + it('getUpgradeExecutor return current upgradeExecutor', async () => { + const randomAddress = privateKeyToAccount(generatePrivateKey()).address; + const randomAddress2 = privateKeyToAccount(generatePrivateKey()).address; + const mockTransport = () => + createTransport({ + key: 'mock', + name: 'Mock Transport', + request: vi.fn(({ method, params }) => { + return mockData({ + logs: [ + mockAdminChangedEvent(zeroAddress, randomAddress), + mockAdminChangedEvent(randomAddress, zeroAddress), + mockAdminChangedEvent(zeroAddress, randomAddress), + mockAdminChangedEvent(randomAddress, randomAddress2), + ], + method, + }); + }) as unknown as EIP1193RequestFn, + type: 'mock', + }); + + const mockClient = createPublicClient({ + transport: mockTransport, + chain: arbitrumSepolia, + }); + + const upgradeExecutor = await getUpgradeExecutor(mockClient, { + rollup: rollupAddress, + }); + + expect(upgradeExecutor).toEqual(randomAddress2); + }); +}); From d701361b511fd20884b41caa6cf2e54b6b1b7d4e Mon Sep 17 00:00:00 2001 From: Christophe Date: Tue, 2 Jul 2024 17:23:05 +0200 Subject: [PATCH 02/11] Add integration tests --- src/createTokenBridge.integration.test.ts | 4 +- src/getUpgradeExecutor.integration.test.ts | 88 ++++++++++++++++++++++ 2 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 src/getUpgradeExecutor.integration.test.ts diff --git a/src/createTokenBridge.integration.test.ts b/src/createTokenBridge.integration.test.ts index 40cbca6c..c5b13024 100644 --- a/src/createTokenBridge.integration.test.ts +++ b/src/createTokenBridge.integration.test.ts @@ -104,7 +104,7 @@ async function checkWethGateways( expect(tokenBridgeContracts.orbitChainContracts.wethGateway).not.toEqual(zeroAddress); } -describe('createTokenBridge utils function', () => { +describe.skip('createTokenBridge utils function', () => { it(`successfully deploys token bridge contracts through token bridge creator`, async () => { const testnodeInformation = getInformationFromTestnode(); @@ -322,7 +322,7 @@ describe('createTokenBridge utils function', () => { }); }); -describe('createTokenBridge', () => { +describe.skip('createTokenBridge', () => { it('successfully deploys token bridge contracts', async () => { const testnodeInformation = getInformationFromTestnode(); diff --git a/src/getUpgradeExecutor.integration.test.ts b/src/getUpgradeExecutor.integration.test.ts new file mode 100644 index 00000000..cfc6c296 --- /dev/null +++ b/src/getUpgradeExecutor.integration.test.ts @@ -0,0 +1,88 @@ +import { describe, it, expect } from 'vitest'; +import { Address, PrivateKeyAccount, createPublicClient, http } from 'viem'; + +import { nitroTestnodeL2 } from './chains'; +import { getInformationFromTestnode, getNitroTestnodePrivateKeyAccounts } from './testHelpers'; +import { getUpgradeExecutor } from './getUpgradeExecutor'; +import { rollupAdminLogicPrepareFunctionData } from './rollupAdminLogicPrepareTransactionRequest'; +import { rollupAdminLogicABI } from './abi'; +import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; + +const { l3UpgradeExecutor, l3Rollup } = getInformationFromTestnode(); +const { l3RollupOwner } = getNitroTestnodePrivateKeyAccounts(); + +const client = createPublicClient({ + chain: nitroTestnodeL2, + transport: http(), +}); + +async function setUpgradeExecutor({ + account, + newOwner, + upgradeExecutor, +}: { + account: PrivateKeyAccount; + newOwner: Address; + upgradeExecutor: Address; +}) { + const { to, data, value } = rollupAdminLogicPrepareFunctionData({ + args: [newOwner], + rollup: l3Rollup, + upgradeExecutor, + abi: rollupAdminLogicABI, + functionName: 'setOwner', + }); + + const request = await client.prepareTransactionRequest({ + chain: client.chain, + to, + data, + value, + account, + }); + + const txHash = await client.sendRawTransaction({ + serializedTransaction: await account.signTransaction({ + ...request, + chainId: nitroTestnodeL2.id, + }), + }); + await client.waitForTransactionReceipt({ + hash: txHash, + }); +} + +// Tests can be enabled once we run one node per integration test +describe('successfully get upgrade executor', () => { + it('when changing upgrade executor multiple time', async () => { + const randomAccount = privateKeyToAccount(generatePrivateKey()).address; + + const initialUpgradeExecutor = await getUpgradeExecutor(client, { + rollup: l3Rollup, + }); + expect(initialUpgradeExecutor?.toLowerCase()).toEqual(l3UpgradeExecutor.toLowerCase()); + + await setUpgradeExecutor({ + upgradeExecutor: l3UpgradeExecutor, + account: l3RollupOwner, + newOwner: randomAccount, + }); + + const currentUpgradeExecutor = await getUpgradeExecutor(client, { + rollup: l3Rollup, + }); + expect(currentUpgradeExecutor?.toLowerCase()).toEqual(randomAccount.toLowerCase()); + + // Revert for future tests + await setUpgradeExecutor({ + upgradeExecutor: l3UpgradeExecutor, + account: l3RollupOwner, + newOwner: l3UpgradeExecutor, + }); + + const finalUpgradeExecutor = await getUpgradeExecutor(client, { + rollup: l3Rollup, + }); + expect(finalUpgradeExecutor?.toLowerCase()).toEqual(l3UpgradeExecutor.toLowerCase()); + }); +}); From ff02ec20289ac193fb18011f5e025e3511a0c83e Mon Sep 17 00:00:00 2001 From: Christophe Date: Tue, 2 Jul 2024 17:25:46 +0200 Subject: [PATCH 03/11] Remove skipped integration tests --- src/createTokenBridge.integration.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/createTokenBridge.integration.test.ts b/src/createTokenBridge.integration.test.ts index c5b13024..40cbca6c 100644 --- a/src/createTokenBridge.integration.test.ts +++ b/src/createTokenBridge.integration.test.ts @@ -104,7 +104,7 @@ async function checkWethGateways( expect(tokenBridgeContracts.orbitChainContracts.wethGateway).not.toEqual(zeroAddress); } -describe.skip('createTokenBridge utils function', () => { +describe('createTokenBridge utils function', () => { it(`successfully deploys token bridge contracts through token bridge creator`, async () => { const testnodeInformation = getInformationFromTestnode(); @@ -322,7 +322,7 @@ describe.skip('createTokenBridge utils function', () => { }); }); -describe.skip('createTokenBridge', () => { +describe('createTokenBridge', () => { it('successfully deploys token bridge contracts', async () => { const testnodeInformation = getInformationFromTestnode(); From d7d0fc532e2210e7d48d07f7012312ee326ebb37 Mon Sep 17 00:00:00 2001 From: Christophe Date: Tue, 2 Jul 2024 17:34:07 +0200 Subject: [PATCH 04/11] Update unit test --- src/getUpgradeExecutor.unit.test.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/getUpgradeExecutor.unit.test.ts b/src/getUpgradeExecutor.unit.test.ts index 2c7ebc0a..e5755527 100644 --- a/src/getUpgradeExecutor.unit.test.ts +++ b/src/getUpgradeExecutor.unit.test.ts @@ -55,6 +55,8 @@ describe('AdminChanged', () => { it('getUpgradeExecutor return current upgradeExecutor', async () => { const randomAddress = privateKeyToAccount(generatePrivateKey()).address; const randomAddress2 = privateKeyToAccount(generatePrivateKey()).address; + const randomAddress3 = privateKeyToAccount(generatePrivateKey()).address; + const mockTransport = () => createTransport({ key: 'mock', @@ -62,9 +64,9 @@ describe('AdminChanged', () => { request: vi.fn(({ method, params }) => { return mockData({ logs: [ - mockAdminChangedEvent(zeroAddress, randomAddress), - mockAdminChangedEvent(randomAddress, zeroAddress), - mockAdminChangedEvent(zeroAddress, randomAddress), + mockAdminChangedEvent(randomAddress3, randomAddress), + mockAdminChangedEvent(randomAddress, randomAddress3), + mockAdminChangedEvent(randomAddress3, randomAddress), mockAdminChangedEvent(randomAddress, randomAddress2), ], method, From 0e11b89aae4ca292486036d9a8e171b2bb7b5494 Mon Sep 17 00:00:00 2001 From: Christophe Date: Wed, 3 Jul 2024 13:27:43 +0200 Subject: [PATCH 05/11] WIP --- src/chains.ts | 28 +++++++++++ src/getUpgradeExecutor.ts | 73 ++++++++++++++++++++--------- src/getUpgradeExecutor.unit.test.ts | 42 ++++++++++++++++- src/testHelpers.ts | 2 + src/types/ParentChain.ts | 2 +- 5 files changed, 122 insertions(+), 25 deletions(-) diff --git a/src/chains.ts b/src/chains.ts index b2525fe4..b7c0870e 100644 --- a/src/chains.ts +++ b/src/chains.ts @@ -96,3 +96,31 @@ export { nitroTestnodeL2, nitroTestnodeL3, }; + +export const xai = defineChain({ + id: 660279, + network: 'Xai Mainnet', + name: 'Xai Mainnet', + nativeCurrency: { name: 'Xai', symbol: 'XAI', decimals: 18 }, + rpcUrls: { + default: { + http: ['https://xai-chain.net/rpc'], + }, + public: { + http: ['https://xai-chain.net/rpc'], + } + }, + blockExplorers: { + default: { + name: 'Blockscout', + url: 'https://explorer.xai-chain.net', + }, + }, + contracts: { + multicall3: { + address: '0xca11bde05977b3631167028862be2a173976ca11', + blockCreated: 222549, + }, + }, + testnet: false, +}) \ No newline at end of file diff --git a/src/getUpgradeExecutor.ts b/src/getUpgradeExecutor.ts index 744f4396..11a2de00 100644 --- a/src/getUpgradeExecutor.ts +++ b/src/getUpgradeExecutor.ts @@ -1,13 +1,16 @@ -import { Address, Chain, PublicClient, Transport, getAbiItem } from 'viem'; -import { rollupAdminLogicABI } from './abi'; +import { Address, Chain, PublicClient, Transport, decodeFunctionData, getAbiItem, getFunctionSelector } from 'viem'; +import { rollupAdminLogicABI, safeL2ABI } from './abi'; import { createRollupFetchTransactionHash } from './createRollupFetchTransactionHash'; +import { isValidParentChainId } from './types/ParentChain'; +import { arbOwnerPublic, upgradeExecutor } from './contracts'; +import { UPGRADE_EXECUTOR_ROLE_ADMIN } from './upgradeExecutorEncodeFunctionData'; const AdminChangedAbi = getAbiItem({ abi: rollupAdminLogicABI, name: 'AdminChanged' }); export type GetUpgradeExecutorParams = { /** Address of the rollup we're getting logs from */ rollup: Address; -}; +} | void; /** * Address of the current upgrade executor */ @@ -28,31 +31,55 @@ export type GetUpgradeExecutorReturnType = Address | undefined; */ export async function getUpgradeExecutor( publicClient: PublicClient, - { rollup }: GetUpgradeExecutorParams, + params: GetUpgradeExecutorParams, ): Promise { - let blockNumber: bigint | 'earliest'; - let createRollupTransactionHash: Address | null = null; + const isParentChain = isValidParentChainId(publicClient.chain?.id) + if (isParentChain && !params) { + throw new Error('[getUpgradeExecutor] requires a rollup address') + } - try { - createRollupTransactionHash = await createRollupFetchTransactionHash({ - rollup, - publicClient, - }); - const receipt = await publicClient.waitForTransactionReceipt({ - hash: createRollupTransactionHash, + // Parent chain, get the newOwner args from the last event + if (isParentChain && params) { + let blockNumber: bigint | 'earliest'; + let createRollupTransactionHash: Address | null = null; + + try { + createRollupTransactionHash = await createRollupFetchTransactionHash({ + rollup: params.rollup, + publicClient, + }); + const receipt = await publicClient.waitForTransactionReceipt({ + hash: createRollupTransactionHash, + }); + blockNumber = receipt.blockNumber; + } catch (e) { + console.warn(`[getUpgradeExecutor] ${(e as any).message}`); + blockNumber = 'earliest'; + } + + const events = await publicClient.getLogs({ + address: params.rollup, + events: [AdminChangedAbi], + fromBlock: blockNumber, + toBlock: 'latest', }); - blockNumber = receipt.blockNumber; - } catch (e) { - console.warn(`[getUpgradeExecutor] ${(e as any).message}`); - blockNumber = 'earliest'; + + return events[events.length - 1].args.newAdmin; } - const events = await publicClient.getLogs({ - address: rollup, - events: [AdminChangedAbi], - fromBlock: blockNumber, - toBlock: 'latest', + // Child chain, check for all chainOwners + const chainOwners = await publicClient.readContract({ + abi: arbOwnerPublic.abi, + functionName: 'getAllChainOwners', + address: arbOwnerPublic.address }); - return events[events.length - 1].args.newAdmin; + const results = await Promise.allSettled(chainOwners.map(chainOwner => publicClient.readContract({ + address: chainOwner, + abi: upgradeExecutor.abi, + functionName: 'hasRole', + args: [UPGRADE_EXECUTOR_ROLE_ADMIN, chainOwner], + }))) + const upgradeExecutorIndex = results.findIndex(p => p.status === 'fulfilled' && p.value === true) + return chainOwners[upgradeExecutorIndex] } diff --git a/src/getUpgradeExecutor.unit.test.ts b/src/getUpgradeExecutor.unit.test.ts index e5755527..0729d62f 100644 --- a/src/getUpgradeExecutor.unit.test.ts +++ b/src/getUpgradeExecutor.unit.test.ts @@ -11,6 +11,7 @@ import { arbitrum, arbitrumSepolia } from 'viem/chains'; import { it, expect, vi, describe } from 'vitest'; import { getUpgradeExecutor } from './getUpgradeExecutor'; import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; +import { xai } from './chains'; const client = createPublicClient({ chain: arbitrum, @@ -41,6 +42,10 @@ function mockData({ logs, method }: { logs: unknown[]; method: 'eth_getLogs' }) return logs; } + if (method === 'eth_call') { + return [padHex('0xe0875cbd144fe66c015a95e5b2d2c15c3b612179')]; + } + return null; } @@ -52,7 +57,7 @@ it('getUpgradeExecutor return current upgradeExecutor (Xai)', async () => { }); describe('AdminChanged', () => { - it('getUpgradeExecutor return current upgradeExecutor', async () => { + it('getUpgradeExecutor return current upgradeExecutor for parent chain', async () => { const randomAddress = privateKeyToAccount(generatePrivateKey()).address; const randomAddress2 = privateKeyToAccount(generatePrivateKey()).address; const randomAddress3 = privateKeyToAccount(generatePrivateKey()).address; @@ -86,4 +91,39 @@ describe('AdminChanged', () => { expect(upgradeExecutor).toEqual(randomAddress2); }); + + it.only('getUpgradeExecutor return current upgradeExecutor for child chain', async () => { + const randomAddress = privateKeyToAccount(generatePrivateKey()).address; + const randomAddress2 = privateKeyToAccount(generatePrivateKey()).address; + const randomAddress3 = privateKeyToAccount(generatePrivateKey()).address; + + const mockTransport = () => + createTransport({ + key: 'mock', + name: 'Mock Transport', + request: vi.fn(({ method, params }) => { + return mockData({ + logs: [ + mockAdminChangedEvent(randomAddress3, randomAddress), + mockAdminChangedEvent(randomAddress, randomAddress3), + mockAdminChangedEvent(randomAddress3, randomAddress), + mockAdminChangedEvent(randomAddress, randomAddress2), + ], + method, + }); + }) as unknown as EIP1193RequestFn, + type: 'mock', + }); + + const mockClient = createPublicClient({ + transport: mockTransport, + chain: xai, + }); + + const upgradeExecutor = await getUpgradeExecutor(mockClient, { + rollup: rollupAddress, + }); + + expect(upgradeExecutor).toEqual(randomAddress2); + }); }); diff --git a/src/testHelpers.ts b/src/testHelpers.ts index fcf38377..8e1707db 100644 --- a/src/testHelpers.ts +++ b/src/testHelpers.ts @@ -81,6 +81,7 @@ type TestnodeInformation = { rollup: Address; sequencerInbox: Address; l3SequencerInbox: Address; + upgradeExecutor: Address; l3Bridge: Address; batchPoster: Address; l3BatchPoster: Address; @@ -120,6 +121,7 @@ export function getInformationFromTestnode(): TestnodeInformation { rollup: deploymentJson['rollup'], sequencerInbox: deploymentJson['sequencer-inbox'], batchPoster: sequencerConfig.node['batch-poster']['parent-chain-wallet'].account, + upgradeExecutor: deploymentJson['upgrade-executor'], l3Bridge: l3DeploymentJson['bridge'], l3Rollup: l3DeploymentJson['rollup'], l3SequencerInbox: l3DeploymentJson['sequencer-inbox'], diff --git a/src/types/ParentChain.ts b/src/types/ParentChain.ts index ff298558..5598cd27 100644 --- a/src/types/ParentChain.ts +++ b/src/types/ParentChain.ts @@ -11,7 +11,7 @@ export type ParentChainPublicClient = Prettify PublicClient & { chain: { id: ParentChainId } } >; -function isValidParentChainId(parentChainId: number | undefined): parentChainId is ParentChainId { +export function isValidParentChainId(parentChainId: number | undefined): parentChainId is ParentChainId { const ids = chains // exclude nitro-testnode L3 from the list of parent chains .filter((chain) => chain.id !== nitroTestnodeL3.id) From 6e6b2341fb877ea0bfadc1534fc54e39b2fd6d10 Mon Sep 17 00:00:00 2001 From: Christophe Date: Thu, 4 Jul 2024 11:56:04 +0000 Subject: [PATCH 06/11] Fix tests --- src/chains.ts | 4 +- src/getUpgradeExecutor.integration.test.ts | 88 +++------------- src/getUpgradeExecutor.ts | 32 +++--- src/getUpgradeExecutor.unit.test.ts | 112 ++++++++------------- src/types/ParentChain.ts | 4 +- 5 files changed, 84 insertions(+), 156 deletions(-) diff --git a/src/chains.ts b/src/chains.ts index b7c0870e..df8588bb 100644 --- a/src/chains.ts +++ b/src/chains.ts @@ -108,7 +108,7 @@ export const xai = defineChain({ }, public: { http: ['https://xai-chain.net/rpc'], - } + }, }, blockExplorers: { default: { @@ -123,4 +123,4 @@ export const xai = defineChain({ }, }, testnet: false, -}) \ No newline at end of file +}); diff --git a/src/getUpgradeExecutor.integration.test.ts b/src/getUpgradeExecutor.integration.test.ts index cfc6c296..58c4c793 100644 --- a/src/getUpgradeExecutor.integration.test.ts +++ b/src/getUpgradeExecutor.integration.test.ts @@ -1,88 +1,32 @@ import { describe, it, expect } from 'vitest'; -import { Address, PrivateKeyAccount, createPublicClient, http } from 'viem'; +import { createPublicClient, http } from 'viem'; -import { nitroTestnodeL2 } from './chains'; -import { getInformationFromTestnode, getNitroTestnodePrivateKeyAccounts } from './testHelpers'; +import { nitroTestnodeL2, nitroTestnodeL3 } from './chains'; +import { getInformationFromTestnode } from './testHelpers'; import { getUpgradeExecutor } from './getUpgradeExecutor'; -import { rollupAdminLogicPrepareFunctionData } from './rollupAdminLogicPrepareTransactionRequest'; -import { rollupAdminLogicABI } from './abi'; -import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; const { l3UpgradeExecutor, l3Rollup } = getInformationFromTestnode(); -const { l3RollupOwner } = getNitroTestnodePrivateKeyAccounts(); - -const client = createPublicClient({ - chain: nitroTestnodeL2, - transport: http(), -}); - -async function setUpgradeExecutor({ - account, - newOwner, - upgradeExecutor, -}: { - account: PrivateKeyAccount; - newOwner: Address; - upgradeExecutor: Address; -}) { - const { to, data, value } = rollupAdminLogicPrepareFunctionData({ - args: [newOwner], - rollup: l3Rollup, - upgradeExecutor, - abi: rollupAdminLogicABI, - functionName: 'setOwner', - }); - - const request = await client.prepareTransactionRequest({ - chain: client.chain, - to, - data, - value, - account, - }); - - const txHash = await client.sendRawTransaction({ - serializedTransaction: await account.signTransaction({ - ...request, - chainId: nitroTestnodeL2.id, - }), - }); - await client.waitForTransactionReceipt({ - hash: txHash, - }); -} // Tests can be enabled once we run one node per integration test describe('successfully get upgrade executor', () => { - it('when changing upgrade executor multiple time', async () => { - const randomAccount = privateKeyToAccount(generatePrivateKey()).address; - - const initialUpgradeExecutor = await getUpgradeExecutor(client, { - rollup: l3Rollup, + it('from parent chain', async () => { + const parentChainClient = createPublicClient({ + chain: nitroTestnodeL2, + transport: http(), }); - expect(initialUpgradeExecutor?.toLowerCase()).toEqual(l3UpgradeExecutor.toLowerCase()); - await setUpgradeExecutor({ - upgradeExecutor: l3UpgradeExecutor, - account: l3RollupOwner, - newOwner: randomAccount, - }); - - const currentUpgradeExecutor = await getUpgradeExecutor(client, { + const initialUpgradeExecutor = await getUpgradeExecutor(parentChainClient, { rollup: l3Rollup, }); - expect(currentUpgradeExecutor?.toLowerCase()).toEqual(randomAccount.toLowerCase()); - - // Revert for future tests - await setUpgradeExecutor({ - upgradeExecutor: l3UpgradeExecutor, - account: l3RollupOwner, - newOwner: l3UpgradeExecutor, - }); + expect(initialUpgradeExecutor?.toLowerCase()).toEqual(l3UpgradeExecutor.toLowerCase()); + }); - const finalUpgradeExecutor = await getUpgradeExecutor(client, { - rollup: l3Rollup, + it('from child chain', async () => { + const childChainClient = createPublicClient({ + chain: nitroTestnodeL3, + transport: http(), }); - expect(finalUpgradeExecutor?.toLowerCase()).toEqual(l3UpgradeExecutor.toLowerCase()); + const initialUpgradeExecutor = await getUpgradeExecutor(childChainClient); + expect(initialUpgradeExecutor?.toLowerCase()).toEqual(l3UpgradeExecutor.toLowerCase()); }); }); diff --git a/src/getUpgradeExecutor.ts b/src/getUpgradeExecutor.ts index 11a2de00..01750c26 100644 --- a/src/getUpgradeExecutor.ts +++ b/src/getUpgradeExecutor.ts @@ -1,5 +1,5 @@ -import { Address, Chain, PublicClient, Transport, decodeFunctionData, getAbiItem, getFunctionSelector } from 'viem'; -import { rollupAdminLogicABI, safeL2ABI } from './abi'; +import { Address, Chain, PublicClient, Transport, getAbiItem } from 'viem'; +import { rollupAdminLogicABI } from './abi'; import { createRollupFetchTransactionHash } from './createRollupFetchTransactionHash'; import { isValidParentChainId } from './types/ParentChain'; import { arbOwnerPublic, upgradeExecutor } from './contracts'; @@ -33,9 +33,9 @@ export async function getUpgradeExecutor( publicClient: PublicClient, params: GetUpgradeExecutorParams, ): Promise { - const isParentChain = isValidParentChainId(publicClient.chain?.id) + const isParentChain = isValidParentChainId(publicClient.chain?.id); if (isParentChain && !params) { - throw new Error('[getUpgradeExecutor] requires a rollup address') + throw new Error('[getUpgradeExecutor] requires a rollup address'); } // Parent chain, get the newOwner args from the last event @@ -71,15 +71,21 @@ export async function getUpgradeExecutor( const chainOwners = await publicClient.readContract({ abi: arbOwnerPublic.abi, functionName: 'getAllChainOwners', - address: arbOwnerPublic.address + address: arbOwnerPublic.address, }); - const results = await Promise.allSettled(chainOwners.map(chainOwner => publicClient.readContract({ - address: chainOwner, - abi: upgradeExecutor.abi, - functionName: 'hasRole', - args: [UPGRADE_EXECUTOR_ROLE_ADMIN, chainOwner], - }))) - const upgradeExecutorIndex = results.findIndex(p => p.status === 'fulfilled' && p.value === true) - return chainOwners[upgradeExecutorIndex] + const results = await Promise.allSettled( + chainOwners.map((chainOwner) => + publicClient.readContract({ + address: chainOwner, + abi: upgradeExecutor.abi, + functionName: 'hasRole', + args: [UPGRADE_EXECUTOR_ROLE_ADMIN, chainOwner], + }), + ), + ); + const upgradeExecutorIndex = results.findIndex( + (p) => p.status === 'fulfilled' && p.value === true, + ); + return chainOwners[upgradeExecutorIndex]; } diff --git a/src/getUpgradeExecutor.unit.test.ts b/src/getUpgradeExecutor.unit.test.ts index 0729d62f..5da79de1 100644 --- a/src/getUpgradeExecutor.unit.test.ts +++ b/src/getUpgradeExecutor.unit.test.ts @@ -1,23 +1,10 @@ -import { - Address, - EIP1193RequestFn, - createPublicClient, - createTransport, - http, - padHex, - zeroAddress, -} from 'viem'; +import { Address, EIP1193RequestFn, createPublicClient, createTransport, http, padHex } from 'viem'; import { arbitrum, arbitrumSepolia } from 'viem/chains'; -import { it, expect, vi, describe } from 'vitest'; +import { it, vi, describe } from 'vitest'; import { getUpgradeExecutor } from './getUpgradeExecutor'; import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; import { xai } from './chains'; -const client = createPublicClient({ - chain: arbitrum, - transport: http(), -}); - const rollupAddress = '0xe0875cbd144fe66c015a95e5b2d2c15c3b612179'; function mockAdminChangedEvent(previousAdmin: Address, newAdmin: Address) { @@ -37,27 +24,28 @@ function mockAdminChangedEvent(previousAdmin: Address, newAdmin: Address) { }; } -function mockData({ logs, method }: { logs: unknown[]; method: 'eth_getLogs' }) { - if (method === 'eth_getLogs') { - return logs; - } - - if (method === 'eth_call') { - return [padHex('0xe0875cbd144fe66c015a95e5b2d2c15c3b612179')]; - } - - return null; -} +describe.concurrent('getUpgradeExecutor', () => { + it('should return upgrade executor on arbitrum one for xai', async ({ expect }) => { + const arbitrumOneClient = createPublicClient({ + chain: arbitrum, + transport: http(), + }); + const upgradeExecutor = await getUpgradeExecutor(arbitrumOneClient, { + rollup: '0xc47dacfbaa80bd9d8112f4e8069482c2a3221336', + }); + expect(upgradeExecutor).toEqual('0x0EE7AD3Cc291343C9952fFd8844e86d294fa513F'); + }); -it('getUpgradeExecutor return current upgradeExecutor (Xai)', async () => { - const upgradeExecutor = await getUpgradeExecutor(client, { - rollup: '0xc47dacfbaa80bd9d8112f4e8069482c2a3221336', + it('should return upgrade executor on xai for xai', async ({ expect }) => { + const xaiClient = createPublicClient({ + chain: xai, + transport: http(), + }); + const upgradeExecutor = await getUpgradeExecutor(xaiClient); + expect(upgradeExecutor).toEqual('0xB30f0939c072255C9a8019B5a52Df9a364861f84'); }); - expect(upgradeExecutor).toEqual('0x0EE7AD3Cc291343C9952fFd8844e86d294fa513F'); -}); -describe('AdminChanged', () => { - it('getUpgradeExecutor return current upgradeExecutor for parent chain', async () => { + it('should return upgrade executor on parent chain with mocked data', async ({ expect }) => { const randomAddress = privateKeyToAccount(generatePrivateKey()).address; const randomAddress2 = privateKeyToAccount(generatePrivateKey()).address; const randomAddress3 = privateKeyToAccount(generatePrivateKey()).address; @@ -67,15 +55,12 @@ describe('AdminChanged', () => { key: 'mock', name: 'Mock Transport', request: vi.fn(({ method, params }) => { - return mockData({ - logs: [ - mockAdminChangedEvent(randomAddress3, randomAddress), - mockAdminChangedEvent(randomAddress, randomAddress3), - mockAdminChangedEvent(randomAddress3, randomAddress), - mockAdminChangedEvent(randomAddress, randomAddress2), - ], - method, - }); + return [ + mockAdminChangedEvent(randomAddress3, randomAddress), + mockAdminChangedEvent(randomAddress, randomAddress3), + mockAdminChangedEvent(randomAddress3, randomAddress), + mockAdminChangedEvent(randomAddress, randomAddress2), + ]; }) as unknown as EIP1193RequestFn, type: 'mock', }); @@ -92,38 +77,29 @@ describe('AdminChanged', () => { expect(upgradeExecutor).toEqual(randomAddress2); }); - it.only('getUpgradeExecutor return current upgradeExecutor for child chain', async () => { + it('should return upgrade executor on child chain with mocked data', async ({ expect }) => { const randomAddress = privateKeyToAccount(generatePrivateKey()).address; const randomAddress2 = privateKeyToAccount(generatePrivateKey()).address; - const randomAddress3 = privateKeyToAccount(generatePrivateKey()).address; - - const mockTransport = () => - createTransport({ - key: 'mock', - name: 'Mock Transport', - request: vi.fn(({ method, params }) => { - return mockData({ - logs: [ - mockAdminChangedEvent(randomAddress3, randomAddress), - mockAdminChangedEvent(randomAddress, randomAddress3), - mockAdminChangedEvent(randomAddress3, randomAddress), - mockAdminChangedEvent(randomAddress, randomAddress2), - ], - method, - }); - }) as unknown as EIP1193RequestFn, - type: 'mock', - }); const mockClient = createPublicClient({ - transport: mockTransport, + transport: http(), chain: xai, }); - const upgradeExecutor = await getUpgradeExecutor(mockClient, { - rollup: rollupAddress, - }); - - expect(upgradeExecutor).toEqual(randomAddress2); + // Mock initial getChainOwners + const readContractSpy = vi.spyOn(mockClient, 'readContract'); + readContractSpy + .mockImplementationOnce(async () => [randomAddress]) // getChainOwners + .mockImplementationOnce(async () => true); // hasRole + + const upgradeExecutor = await getUpgradeExecutor(mockClient); + expect(upgradeExecutor).toEqual(randomAddress); + + readContractSpy + .mockImplementationOnce(async () => [randomAddress, randomAddress2]) // second getChainOwners + .mockImplementationOnce(async () => false) + .mockImplementationOnce(async () => true); + const upgradeExecutor2 = await getUpgradeExecutor(mockClient); + expect(upgradeExecutor2).toEqual(randomAddress2); }); }); diff --git a/src/types/ParentChain.ts b/src/types/ParentChain.ts index 5598cd27..261a24cb 100644 --- a/src/types/ParentChain.ts +++ b/src/types/ParentChain.ts @@ -11,7 +11,9 @@ export type ParentChainPublicClient = Prettify PublicClient & { chain: { id: ParentChainId } } >; -export function isValidParentChainId(parentChainId: number | undefined): parentChainId is ParentChainId { +export function isValidParentChainId( + parentChainId: number | undefined, +): parentChainId is ParentChainId { const ids = chains // exclude nitro-testnode L3 from the list of parent chains .filter((chain) => chain.id !== nitroTestnodeL3.id) From f078c8fc28d882133a3cfa82a04eec02927e52ac Mon Sep 17 00:00:00 2001 From: Christophe Date: Thu, 4 Jul 2024 14:34:16 +0200 Subject: [PATCH 07/11] Fix expected value --- src/getUpgradeExecutor.integration.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/getUpgradeExecutor.integration.test.ts b/src/getUpgradeExecutor.integration.test.ts index 58c4c793..130e5e95 100644 --- a/src/getUpgradeExecutor.integration.test.ts +++ b/src/getUpgradeExecutor.integration.test.ts @@ -5,7 +5,7 @@ import { nitroTestnodeL2, nitroTestnodeL3 } from './chains'; import { getInformationFromTestnode } from './testHelpers'; import { getUpgradeExecutor } from './getUpgradeExecutor'; -const { l3UpgradeExecutor, l3Rollup } = getInformationFromTestnode(); +const { upgradeExecutor, l3UpgradeExecutor, l3Rollup } = getInformationFromTestnode(); // Tests can be enabled once we run one node per integration test describe('successfully get upgrade executor', () => { @@ -15,10 +15,10 @@ describe('successfully get upgrade executor', () => { transport: http(), }); - const initialUpgradeExecutor = await getUpgradeExecutor(parentChainClient, { + const upgradeExecutor = await getUpgradeExecutor(parentChainClient, { rollup: l3Rollup, }); - expect(initialUpgradeExecutor?.toLowerCase()).toEqual(l3UpgradeExecutor.toLowerCase()); + expect(upgradeExecutor?.toLowerCase()).toEqual(l3UpgradeExecutor); }); it('from child chain', async () => { @@ -26,7 +26,7 @@ describe('successfully get upgrade executor', () => { chain: nitroTestnodeL3, transport: http(), }); - const initialUpgradeExecutor = await getUpgradeExecutor(childChainClient); - expect(initialUpgradeExecutor?.toLowerCase()).toEqual(l3UpgradeExecutor.toLowerCase()); + const upgradeExecutor = await getUpgradeExecutor(childChainClient); + expect(upgradeExecutor).toEqual(upgradeExecutor); }); }); From c795abe8faa51fc7f1a12cd39434c3f7164ea34f Mon Sep 17 00:00:00 2001 From: Christophe Date: Mon, 8 Jul 2024 14:00:08 +0000 Subject: [PATCH 08/11] Remove unused import --- src/getUpgradeExecutor.integration.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/getUpgradeExecutor.integration.test.ts b/src/getUpgradeExecutor.integration.test.ts index 130e5e95..bf2bd80d 100644 --- a/src/getUpgradeExecutor.integration.test.ts +++ b/src/getUpgradeExecutor.integration.test.ts @@ -5,7 +5,7 @@ import { nitroTestnodeL2, nitroTestnodeL3 } from './chains'; import { getInformationFromTestnode } from './testHelpers'; import { getUpgradeExecutor } from './getUpgradeExecutor'; -const { upgradeExecutor, l3UpgradeExecutor, l3Rollup } = getInformationFromTestnode(); +const { l3UpgradeExecutor, l3Rollup } = getInformationFromTestnode(); // Tests can be enabled once we run one node per integration test describe('successfully get upgrade executor', () => { From 00c3e8cfa34661727844d80f60336e8d7c9a0b24 Mon Sep 17 00:00:00 2001 From: Christophe Date: Mon, 8 Jul 2024 18:34:34 +0200 Subject: [PATCH 09/11] Move xai from chains to testHelper --- src/chains.ts | 28 --------------------------- src/getUpgradeExecutor.unit.test.ts | 2 +- src/testHelpers.ts | 30 ++++++++++++++++++++++++++++- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/chains.ts b/src/chains.ts index df8588bb..b2525fe4 100644 --- a/src/chains.ts +++ b/src/chains.ts @@ -96,31 +96,3 @@ export { nitroTestnodeL2, nitroTestnodeL3, }; - -export const xai = defineChain({ - id: 660279, - network: 'Xai Mainnet', - name: 'Xai Mainnet', - nativeCurrency: { name: 'Xai', symbol: 'XAI', decimals: 18 }, - rpcUrls: { - default: { - http: ['https://xai-chain.net/rpc'], - }, - public: { - http: ['https://xai-chain.net/rpc'], - }, - }, - blockExplorers: { - default: { - name: 'Blockscout', - url: 'https://explorer.xai-chain.net', - }, - }, - contracts: { - multicall3: { - address: '0xca11bde05977b3631167028862be2a173976ca11', - blockCreated: 222549, - }, - }, - testnet: false, -}); diff --git a/src/getUpgradeExecutor.unit.test.ts b/src/getUpgradeExecutor.unit.test.ts index 5da79de1..139941f6 100644 --- a/src/getUpgradeExecutor.unit.test.ts +++ b/src/getUpgradeExecutor.unit.test.ts @@ -3,7 +3,7 @@ import { arbitrum, arbitrumSepolia } from 'viem/chains'; import { it, vi, describe } from 'vitest'; import { getUpgradeExecutor } from './getUpgradeExecutor'; import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; -import { xai } from './chains'; +import { xai } from './testHelpers'; const rollupAddress = '0xe0875cbd144fe66c015a95e5b2d2c15c3b612179'; diff --git a/src/testHelpers.ts b/src/testHelpers.ts index 8e1707db..f5dbc2af 100644 --- a/src/testHelpers.ts +++ b/src/testHelpers.ts @@ -1,4 +1,4 @@ -import { Address, Client, PublicClient, zeroAddress } from 'viem'; +import { Address, PublicClient, defineChain, zeroAddress } from 'viem'; import { privateKeyToAccount, PrivateKeyAccount } from 'viem/accounts'; import { config } from 'dotenv'; import { execSync } from 'node:child_process'; @@ -181,3 +181,31 @@ export async function createRollupHelper({ createRollupInformation, }; } + +export const xai = defineChain({ + id: 660279, + network: 'Xai Mainnet', + name: 'Xai Mainnet', + nativeCurrency: { name: 'Xai', symbol: 'XAI', decimals: 18 }, + rpcUrls: { + default: { + http: ['https://xai-chain.net/rpc'], + }, + public: { + http: ['https://xai-chain.net/rpc'], + }, + }, + blockExplorers: { + default: { + name: 'Blockscout', + url: 'https://explorer.xai-chain.net', + }, + }, + contracts: { + multicall3: { + address: '0xca11bde05977b3631167028862be2a173976ca11', + blockCreated: 222549, + }, + }, + testnet: false, +}); From ebfc3d6bb35d705dda62192723599673275facc7 Mon Sep 17 00:00:00 2001 From: Christophe Date: Tue, 9 Jul 2024 17:19:00 +0200 Subject: [PATCH 10/11] Address review comments --- .../getUpgradeExecutor.integration.test.ts.snap | 3 +++ src/getUpgradeExecutor.integration.test.ts | 2 +- src/getUpgradeExecutor.ts | 15 +++++++++++++-- src/testHelpers.ts | 12 ------------ vitest.integration.config.ts | 2 +- 5 files changed, 18 insertions(+), 16 deletions(-) create mode 100644 src/__snapshots__/getUpgradeExecutor.integration.test.ts.snap diff --git a/src/__snapshots__/getUpgradeExecutor.integration.test.ts.snap b/src/__snapshots__/getUpgradeExecutor.integration.test.ts.snap new file mode 100644 index 00000000..5802ac4b --- /dev/null +++ b/src/__snapshots__/getUpgradeExecutor.integration.test.ts.snap @@ -0,0 +1,3 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`successfully get upgrade executor > from child chain 1`] = `"0x24198F8A339cd3C47AEa3A764A20d2dDaB4D1b5b"`; diff --git a/src/getUpgradeExecutor.integration.test.ts b/src/getUpgradeExecutor.integration.test.ts index bf2bd80d..399c18ca 100644 --- a/src/getUpgradeExecutor.integration.test.ts +++ b/src/getUpgradeExecutor.integration.test.ts @@ -27,6 +27,6 @@ describe('successfully get upgrade executor', () => { transport: http(), }); const upgradeExecutor = await getUpgradeExecutor(childChainClient); - expect(upgradeExecutor).toEqual(upgradeExecutor); + expect(upgradeExecutor).toMatchSnapshot(); }); }); diff --git a/src/getUpgradeExecutor.ts b/src/getUpgradeExecutor.ts index 01750c26..493d5ebc 100644 --- a/src/getUpgradeExecutor.ts +++ b/src/getUpgradeExecutor.ts @@ -17,6 +17,9 @@ export type GetUpgradeExecutorParams = { export type GetUpgradeExecutorReturnType = Address | undefined; /** + * Return upgrade executor address for a parent or child chain + * + * Docs: https://docs.arbitrum.io/launch-orbit-chain/concepts/chain-ownership * * @param {PublicClient} publicClient - The chain Viem Public Client * @param {GetUpgradeExecutorParams} GetUpgradeExecutorParams {@link GetUpgradeExecutorParams} @@ -41,10 +44,9 @@ export async function getUpgradeExecutor( // Parent chain, get the newOwner args from the last event if (isParentChain && params) { let blockNumber: bigint | 'earliest'; - let createRollupTransactionHash: Address | null = null; try { - createRollupTransactionHash = await createRollupFetchTransactionHash({ + const createRollupTransactionHash = await createRollupFetchTransactionHash({ rollup: params.rollup, publicClient, }); @@ -59,6 +61,15 @@ export async function getUpgradeExecutor( const events = await publicClient.getLogs({ address: params.rollup, + /** + * The event comes from: + * - event AdminChanged(address previousAdmin, address newAdmin) + * - ERC1967Upgrade + * - DoubleLogicUUPSUpgradeable + * - RollupAdminLogic + * + * see https://github.com/OffchainLabs/nitro-contracts/blob/90037b996509312ef1addb3f9352457b8a99d6a6/src/rollup/RollupAdminLogic.sol#L182 + */ events: [AdminChangedAbi], fromBlock: blockNumber, toBlock: 'latest', diff --git a/src/testHelpers.ts b/src/testHelpers.ts index f5dbc2af..3d108391 100644 --- a/src/testHelpers.ts +++ b/src/testHelpers.ts @@ -195,17 +195,5 @@ export const xai = defineChain({ http: ['https://xai-chain.net/rpc'], }, }, - blockExplorers: { - default: { - name: 'Blockscout', - url: 'https://explorer.xai-chain.net', - }, - }, - contracts: { - multicall3: { - address: '0xca11bde05977b3631167028862be2a173976ca11', - blockCreated: 222549, - }, - }, testnet: false, }); diff --git a/vitest.integration.config.ts b/vitest.integration.config.ts index 9fbef818..195beb99 100644 --- a/vitest.integration.config.ts +++ b/vitest.integration.config.ts @@ -8,7 +8,7 @@ export default mergeConfig( // allow tests to run for 7 minutes as retryables can take a while testTimeout: 7 * 60 * 1000, exclude: [...configDefaults.exclude, './src/**/*.unit.test.ts'], - include: ['./src/**/*.integration.test.ts'], + include: ['./src/getUpgradeExecutor.integration.test.ts'], fileParallelism: false, // Run all integration tests sequentially }, }), From 5e3afecf3adab2b4162471e7ea3abba5bf814942 Mon Sep 17 00:00:00 2001 From: Christophe Date: Tue, 9 Jul 2024 15:46:03 +0000 Subject: [PATCH 11/11] Review comment --- src/getUpgradeExecutor.ts | 6 +++--- vitest.integration.config.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/getUpgradeExecutor.ts b/src/getUpgradeExecutor.ts index 493d5ebc..d6cd9059 100644 --- a/src/getUpgradeExecutor.ts +++ b/src/getUpgradeExecutor.ts @@ -10,7 +10,7 @@ const AdminChangedAbi = getAbiItem({ abi: rollupAdminLogicABI, name: 'AdminChang export type GetUpgradeExecutorParams = { /** Address of the rollup we're getting logs from */ rollup: Address; -} | void; +}; /** * Address of the current upgrade executor */ @@ -34,10 +34,10 @@ export type GetUpgradeExecutorReturnType = Address | undefined; */ export async function getUpgradeExecutor( publicClient: PublicClient, - params: GetUpgradeExecutorParams, + params?: GetUpgradeExecutorParams, ): Promise { const isParentChain = isValidParentChainId(publicClient.chain?.id); - if (isParentChain && !params) { + if (isParentChain && !params?.rollup) { throw new Error('[getUpgradeExecutor] requires a rollup address'); } diff --git a/vitest.integration.config.ts b/vitest.integration.config.ts index 195beb99..9fbef818 100644 --- a/vitest.integration.config.ts +++ b/vitest.integration.config.ts @@ -8,7 +8,7 @@ export default mergeConfig( // allow tests to run for 7 minutes as retryables can take a while testTimeout: 7 * 60 * 1000, exclude: [...configDefaults.exclude, './src/**/*.unit.test.ts'], - include: ['./src/getUpgradeExecutor.integration.test.ts'], + include: ['./src/**/*.integration.test.ts'], fileParallelism: false, // Run all integration tests sequentially }, }),