From d5e2d8e4916f2e9394636c04be90f5fa8c1849a0 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 18 Aug 2026 13:37:49 +0200 Subject: [PATCH] fix: batch getLogs in upgradeExecutorFetchPrivilegedAccounts `upgradeExecutorFetchPrivilegedAccounts` queried the RoleGranted and RoleRevoked events with a single `fromBlock: 0n, toBlock: 'latest'` call. Most RPC providers cap `eth_getLogs` to a bounded block range, so this fails with "query range is too big" on nearly every endpoint, including https://sepolia-rollup.arbitrum.io/rpc. Use `getLogsWithBatching`, the same helper the other fetchers (getBatchPosters, getValidators, getKeysets, ...) already use: it tries the full range first and falls back to fixed-size batches on failure, so it works against range-limited RPCs. closes #642 --- src/upgradeExecutor.unit.test.ts | 34 ++++++++++++++++++- src/upgradeExecutorFetchPrivilegedAccounts.ts | 7 ++-- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/upgradeExecutor.unit.test.ts b/src/upgradeExecutor.unit.test.ts index d7ea7cf8b..6415e1dfa 100644 --- a/src/upgradeExecutor.unit.test.ts +++ b/src/upgradeExecutor.unit.test.ts @@ -1,4 +1,4 @@ -import { it, expect } from 'vitest'; +import { it, expect, vi } from 'vitest'; import { upgradeExecutorFetchPrivilegedAccounts } from './upgradeExecutorFetchPrivilegedAccounts'; import { UPGRADE_EXECUTOR_ROLE_ADMIN, @@ -6,6 +6,7 @@ import { upgradeExecutorEncodeFunctionData, } from './upgradeExecutorEncodeFunctionData'; import { createPublicClient, http } from 'viem'; +import { getEarliestRollupCreatorDeploymentBlockNumber } from './utils/getEarliestRollupCreatorDeploymentBlockNumber'; import { arbitrum } from 'viem/chains'; const publicClient = createPublicClient({ @@ -42,3 +43,34 @@ it('it fetches the right privileged accounts from an UpgradeExecutor', async () expect(privilegedAccounts[upgradeExecutorAddress]).toEqual([UPGRADE_EXECUTOR_ROLE_ADMIN]); expect(privilegedAccounts[chainOwner]).toEqual([UPGRADE_EXECUTOR_ROLE_EXECUTOR]); }); + +it('batches the getLogs queries when the RPC rejects the full range (#642)', async () => { + const batchingClient = createPublicClient({ chain: arbitrum, transport: http() }); + + // keep the batched range tiny and network-free + const lowerLimit = getEarliestRollupCreatorDeploymentBlockNumber(batchingClient); + batchingClient.getBlockNumber = vi.fn().mockResolvedValue(lowerLimit + 3n); + + const upgradeExecutorAddress = '0x0611b78A42903a537BE7a2f9a8783BE39AC63cD9'; + const account = '0x46A78349aBA0369D18292a285DE6d5FC5CC2de5c'; + const roleGrantedLog = { args: { role: UPGRADE_EXECUTOR_ROLE_EXECUTOR, account } }; + + const getLogsMock = vi.fn(); + batchingClient.getLogs = getLogsMock; + getLogsMock + // RoleGranted: full-range rejected, then the batched call returns the event + .mockRejectedValueOnce(new Error('query range is too big')) + .mockResolvedValueOnce([roleGrantedLog]) + // RoleRevoked: full-range rejected, then the batched call returns nothing + .mockRejectedValueOnce(new Error('query range is too big')) + .mockResolvedValue([]); + + const privilegedAccounts = await upgradeExecutorFetchPrivilegedAccounts({ + upgradeExecutorAddress, + publicClient: batchingClient, + }); + + // the full-range attempt for each event is retried in batches rather than thrown + expect(getLogsMock.mock.calls.length).toBeGreaterThanOrEqual(4); + expect(privilegedAccounts[account]).toEqual([UPGRADE_EXECUTOR_ROLE_EXECUTOR]); +}); diff --git a/src/upgradeExecutorFetchPrivilegedAccounts.ts b/src/upgradeExecutorFetchPrivilegedAccounts.ts index 1103d5cb4..a70a91ea5 100644 --- a/src/upgradeExecutorFetchPrivilegedAccounts.ts +++ b/src/upgradeExecutorFetchPrivilegedAccounts.ts @@ -1,6 +1,7 @@ import { Address, PublicClient, Transport, Chain } from 'viem'; import { AbiEvent } from 'abitype'; import { UpgradeExecutorRole } from './upgradeExecutorEncodeFunctionData'; +import { getLogsWithBatching } from './utils/getLogsWithBatching'; /** * This type is for the params of the {@link upgradeExecutorFetchPrivilegedAccounts} function @@ -97,11 +98,10 @@ export async function upgradeExecutorFetchPrivilegedAccounts