From 6ae42981fed3986ace3f8d7197eae90de194d2d8 Mon Sep 17 00:00:00 2001 From: Christophe Date: Wed, 25 Sep 2024 20:00:17 +0200 Subject: [PATCH 1/3] Feat: Add v1 upgradeExecutor setters --- src/actions/buildAddExecutor.ts | 43 +++++++++++++++++++++ src/actions/buildRemoveExecutor.ts | 43 +++++++++++++++++++++ src/prepareUpgradeExecutorCallParameters.ts | 3 +- 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/actions/buildAddExecutor.ts create mode 100644 src/actions/buildRemoveExecutor.ts diff --git a/src/actions/buildAddExecutor.ts b/src/actions/buildAddExecutor.ts new file mode 100644 index 00000000..f77d60d7 --- /dev/null +++ b/src/actions/buildAddExecutor.ts @@ -0,0 +1,43 @@ +import { Address, Chain, PrepareTransactionRequestParameters, PublicClient, Transport } from 'viem'; +import { upgradeExecutorABI } from '../contracts/UpgradeExecutor'; +import { + ActionParameters, + PrepareTransactionRequestReturnTypeWithChainId, + WithAccount, +} from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { UPGRADE_EXECUTOR_ROLE_EXECUTOR } from '../upgradeExecutorEncodeFunctionData'; +import { prepareUpgradeExecutorCallParameters } from '../prepareUpgradeExecutorCallParameters'; + +export type BuildAddExecutorParameters = Prettify< + WithAccount< + ActionParameters< + { + address: Address; + }, + 'upgradeExecutor', + Curried + > + > +>; + +export type BuildAddExecutorReturnType = PrepareTransactionRequestReturnTypeWithChainId; + +export async function buildAddExecutor( + client: PublicClient, + { account, upgradeExecutor: upgradeExecutorAddress, params }: BuildAddExecutorParameters, +): Promise { + const request = await client.prepareTransactionRequest({ + chain: client.chain as Chain | undefined, + account, + ...prepareUpgradeExecutorCallParameters({ + to: upgradeExecutorAddress, + upgradeExecutor: upgradeExecutorAddress, + args: [UPGRADE_EXECUTOR_ROLE_EXECUTOR, params.address], + abi: upgradeExecutorABI, + functionName: 'grantRole', + }), + } satisfies PrepareTransactionRequestParameters); + + return { ...request, chainId: client.chain.id }; +} diff --git a/src/actions/buildRemoveExecutor.ts b/src/actions/buildRemoveExecutor.ts new file mode 100644 index 00000000..25e84769 --- /dev/null +++ b/src/actions/buildRemoveExecutor.ts @@ -0,0 +1,43 @@ +import { Address, Chain, PrepareTransactionRequestParameters, PublicClient, Transport } from 'viem'; +import { upgradeExecutorABI } from '../contracts/UpgradeExecutor'; +import { + ActionParameters, + PrepareTransactionRequestReturnTypeWithChainId, + WithAccount, +} from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { UPGRADE_EXECUTOR_ROLE_EXECUTOR } from '../upgradeExecutorEncodeFunctionData'; +import { prepareUpgradeExecutorCallParameters } from '../prepareUpgradeExecutorCallParameters'; + +export type BuildRemoveExecutorParameters = Prettify< + WithAccount< + ActionParameters< + { + address: Address; + }, + 'upgradeExecutor', + Curried + > + > +>; + +export type BuildRemoveExecutorReturnType = PrepareTransactionRequestReturnTypeWithChainId; + +export async function buildRemoveExecutor( + client: PublicClient, + { account, upgradeExecutor: upgradeExecutorAddress, params }: BuildRemoveExecutorParameters, +): Promise { + const request = await client.prepareTransactionRequest({ + chain: client.chain as Chain | undefined, + account, + ...prepareUpgradeExecutorCallParameters({ + to: upgradeExecutorAddress, + upgradeExecutor: upgradeExecutorAddress, + args: [UPGRADE_EXECUTOR_ROLE_EXECUTOR, params.address], + abi: upgradeExecutorABI, + functionName: 'revokeRole', + }), + } satisfies PrepareTransactionRequestParameters); + + return { ...request, chainId: client.chain.id }; +} diff --git a/src/prepareUpgradeExecutorCallParameters.ts b/src/prepareUpgradeExecutorCallParameters.ts index dcde21c0..617995d5 100644 --- a/src/prepareUpgradeExecutorCallParameters.ts +++ b/src/prepareUpgradeExecutorCallParameters.ts @@ -10,8 +10,9 @@ import { upgradeExecutorEncodeFunctionData, UpgradeExecutorFunctionName, } from './upgradeExecutorEncodeFunctionData'; +import { upgradeExecutorABI } from './contracts/UpgradeExecutor'; -type ABIs = typeof sequencerInboxABI | typeof arbOwnerABI; +type ABIs = typeof sequencerInboxABI | typeof arbOwnerABI | typeof upgradeExecutorABI; type FunctionName = GetFunctionName; type EncodeFunctionDataParameters< From 3a29ffa0218888cb7f98f22454d468da870188a0 Mon Sep 17 00:00:00 2001 From: Christophe Date: Fri, 28 Jun 2024 15:30:19 +0000 Subject: [PATCH 2/3] Feat: Add v1 upgradeExecutor getters --- src/actions/hasRole.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/actions/hasRole.ts diff --git a/src/actions/hasRole.ts b/src/actions/hasRole.ts new file mode 100644 index 00000000..ef0a0c1a --- /dev/null +++ b/src/actions/hasRole.ts @@ -0,0 +1,27 @@ +import { Address, Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { upgradeExecutorABI } from '../contracts/UpgradeExecutor'; +import { UpgradeExecutorRole } from '../upgradeExecutorEncodeFunctionData'; +import { ActionParameters } from '../types/Actions'; + +export type HasRoleParameters = ActionParameters< + { + role: UpgradeExecutorRole; + address: Address; + }, + 'upgradeExecutor', + Curried +>; + +export type HasRoleReturnType = ReadContractReturnType; + +export async function hasRole( + client: PublicClient, + { upgradeExecutor, params }: HasRoleParameters, +): Promise { + return client.readContract({ + abi: upgradeExecutorABI, + functionName: 'hasRole', + address: upgradeExecutor, + args: [params.role, params.address], + }); +} From 09b6ef9fca47bc0c82e3c64124a32c4de70c4c98 Mon Sep 17 00:00:00 2001 From: Christophe Date: Wed, 25 Sep 2024 20:46:24 +0200 Subject: [PATCH 3/3] test: Add upgradeExecutor integration tests --- .../upgradeExecutor.integration.test.ts | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/actions/upgradeExecutor.integration.test.ts diff --git a/src/actions/upgradeExecutor.integration.test.ts b/src/actions/upgradeExecutor.integration.test.ts new file mode 100644 index 00000000..0d8e8241 --- /dev/null +++ b/src/actions/upgradeExecutor.integration.test.ts @@ -0,0 +1,93 @@ +import { describe, it, expect } from 'vitest'; +import { getInformationFromTestnode, getNitroTestnodePrivateKeyAccounts } from '../testHelpers'; +import { Address, createPublicClient, http } from 'viem'; +import { nitroTestnodeL2 } from '../chains'; +import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; +import { upgradeExecutorFetchPrivilegedAccounts } from '../upgradeExecutorFetchPrivilegedAccounts'; +import { buildAddExecutor } from './buildAddExecutor'; +import { UPGRADE_EXECUTOR_ROLE_EXECUTOR } from '../upgradeExecutorEncodeFunctionData'; +import { buildRemoveExecutor } from './buildRemoveExecutor'; +import { hasRole } from './hasRole'; + +const { l3UpgradeExecutor } = getInformationFromTestnode(); +const { l3RollupOwner } = getNitroTestnodePrivateKeyAccounts(); + +const client = createPublicClient({ + chain: nitroTestnodeL2, + transport: http(), +}); + +describe('Upgrade executor', () => { + it('buildAddExecutor and buildRemoveExecutor update upgradeExecutor', async () => { + async function changeUpgradeExecutor(address: Address, add: boolean) { + const fn = add ? buildAddExecutor : buildRemoveExecutor; + const transactionRequest = await fn(client, { + account: l3RollupOwner.address, + upgradeExecutor: l3UpgradeExecutor, + params: { + address, + }, + }); + const txHash = await client.sendRawTransaction({ + serializedTransaction: await l3RollupOwner.signTransaction(transactionRequest), + }); + await client.waitForTransactionReceipt({ hash: txHash }); + } + const addUpgradeExecutor = (address: Address) => changeUpgradeExecutor(address, true); + const removeUpgradeExecutor = (address: Address) => changeUpgradeExecutor(address, false); + + const randomAddress = privateKeyToAccount(generatePrivateKey()).address; + + const initialState = await upgradeExecutorFetchPrivilegedAccounts({ + upgradeExecutorAddress: l3UpgradeExecutor, + publicClient: client, + }); + + expect( + await hasRole(client, { + params: { + role: UPGRADE_EXECUTOR_ROLE_EXECUTOR, + address: randomAddress, + }, + upgradeExecutor: l3UpgradeExecutor, + }), + ).toBeFalsy(); + + await addUpgradeExecutor(randomAddress); + expect( + await upgradeExecutorFetchPrivilegedAccounts({ + upgradeExecutorAddress: l3UpgradeExecutor, + publicClient: client, + }), + ).toEqual({ + ...initialState, + [randomAddress]: [UPGRADE_EXECUTOR_ROLE_EXECUTOR], + }); + expect( + await hasRole(client, { + params: { + role: UPGRADE_EXECUTOR_ROLE_EXECUTOR, + address: randomAddress, + }, + upgradeExecutor: l3UpgradeExecutor, + }), + ).toBeTruthy(); + + await removeUpgradeExecutor(randomAddress); + expect( + await upgradeExecutorFetchPrivilegedAccounts({ + upgradeExecutorAddress: l3UpgradeExecutor, + publicClient: client, + }), + ).toEqual(initialState); + expect( + await hasRole(client, { + params: { + role: UPGRADE_EXECUTOR_ROLE_EXECUTOR, + address: randomAddress, + }, + upgradeExecutor: l3UpgradeExecutor, + }), + ).toBeFalsy(); + }); +});