From 64edde27f0559cd55822b4b55362cdafef46ad01 Mon Sep 17 00:00:00 2001 From: Christophe Date: Tue, 24 Sep 2024 16:58:17 +0200 Subject: [PATCH 1/5] feat: Add v1 arbOwnerPublic setters --- src/actions/buildAddChainOwner.ts | 42 +++++++++++++++++++ src/actions/buildRemoveChainOwner.ts | 41 ++++++++++++++++++ src/actions/buildSetMaxTxGasLimit.ts | 41 ++++++++++++++++++ src/actions/buildSetParentPricePerUnit.ts | 41 ++++++++++++++++++ .../buildSetParentPricingRewardRate.ts | 42 +++++++++++++++++++ .../buildSetParentPricingRewardRecipient.ts | 42 +++++++++++++++++++ src/actions/buildSetSpeedLimit.ts | 41 ++++++++++++++++++ src/types/validateChildChainPublicClient.ts | 16 +++++++ 8 files changed, 306 insertions(+) create mode 100644 src/actions/buildAddChainOwner.ts create mode 100644 src/actions/buildRemoveChainOwner.ts create mode 100644 src/actions/buildSetMaxTxGasLimit.ts create mode 100644 src/actions/buildSetParentPricePerUnit.ts create mode 100644 src/actions/buildSetParentPricingRewardRate.ts create mode 100644 src/actions/buildSetParentPricingRewardRecipient.ts create mode 100644 src/actions/buildSetSpeedLimit.ts create mode 100644 src/types/validateChildChainPublicClient.ts diff --git a/src/actions/buildAddChainOwner.ts b/src/actions/buildAddChainOwner.ts new file mode 100644 index 00000000..69e49cf2 --- /dev/null +++ b/src/actions/buildAddChainOwner.ts @@ -0,0 +1,42 @@ +import { Address, Chain, PrepareTransactionRequestParameters, PublicClient, Transport } from 'viem'; +import { arbOwnerABI, arbOwnerAddress } from '../contracts/ArbOwner'; +import { + PrepareTransactionRequestReturnTypeWithChainId, + WithAccount, + WithUpgradeExecutor, +} from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { prepareUpgradeExecutorCallParameters } from '../prepareUpgradeExecutorCallParameters'; +import { validateChildChainPublicClient } from '../types/validateChildChainPublicClient'; + +export type BuildAddChainOwnerParameters = Prettify< + WithUpgradeExecutor< + WithAccount<{ + params: { + newOwner: Address; + }; + }> + > +>; +export type BuildAddChainOwnerReturnType = PrepareTransactionRequestReturnTypeWithChainId; + +export async function buildAddChainOwner( + client: PublicClient, + { account, upgradeExecutor, params }: BuildAddChainOwnerParameters, +): Promise { + const validatedPublicClient = validateChildChainPublicClient(client); + + const request = await client.prepareTransactionRequest({ + chain: client.chain as Chain | undefined, + account, + ...prepareUpgradeExecutorCallParameters({ + to: arbOwnerAddress, + upgradeExecutor, + args: [params.newOwner], + abi: arbOwnerABI, + functionName: 'addChainOwner', + }), + } satisfies PrepareTransactionRequestParameters); + + return { ...request, chainId: validatedPublicClient.chain.id }; +} diff --git a/src/actions/buildRemoveChainOwner.ts b/src/actions/buildRemoveChainOwner.ts new file mode 100644 index 00000000..cfbb2696 --- /dev/null +++ b/src/actions/buildRemoveChainOwner.ts @@ -0,0 +1,41 @@ +import { Address, Chain, PrepareTransactionRequestParameters, PublicClient, Transport } from 'viem'; +import { arbOwnerABI, arbOwnerAddress } from '../contracts/ArbOwner'; +import { + PrepareTransactionRequestReturnTypeWithChainId, + WithAccount, + WithUpgradeExecutor, +} from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { validateChildChainPublicClient } from '../types/validateChildChainPublicClient'; +import { prepareUpgradeExecutorCallParameters } from '../prepareUpgradeExecutorCallParameters'; + +export type BuildRemoveChainOwnerParameters = Prettify< + WithUpgradeExecutor< + WithAccount<{ + params: { owner: Address }; + }> + > +>; + +export type BuildRemoveChainOwnerReturnType = PrepareTransactionRequestReturnTypeWithChainId; + +export async function buildRemoveChainOwner( + client: PublicClient, + { account, upgradeExecutor, params }: BuildRemoveChainOwnerParameters, +): Promise { + const validatedPublicClient = validateChildChainPublicClient(client); + + const request = await client.prepareTransactionRequest({ + chain: client.chain as Chain | undefined, + account, + ...prepareUpgradeExecutorCallParameters({ + to: arbOwnerAddress, + upgradeExecutor, + args: [params.owner], + abi: arbOwnerABI, + functionName: 'removeChainOwner', + }), + } satisfies PrepareTransactionRequestParameters); + + return { ...request, chainId: validatedPublicClient.chain.id }; +} diff --git a/src/actions/buildSetMaxTxGasLimit.ts b/src/actions/buildSetMaxTxGasLimit.ts new file mode 100644 index 00000000..a7b06ecd --- /dev/null +++ b/src/actions/buildSetMaxTxGasLimit.ts @@ -0,0 +1,41 @@ +import { Chain, PrepareTransactionRequestParameters, PublicClient, Transport } from 'viem'; +import { arbOwnerABI, arbOwnerAddress } from '../contracts/ArbOwner'; +import { + PrepareTransactionRequestReturnTypeWithChainId, + WithAccount, + WithUpgradeExecutor, +} from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { validateChildChainPublicClient } from '../types/validateChildChainPublicClient'; +import { prepareUpgradeExecutorCallParameters } from '../prepareUpgradeExecutorCallParameters'; + +export type BuildSetMaxTxGasLimitParameters = Prettify< + WithUpgradeExecutor< + WithAccount<{ + params: { limit: bigint }; + }> + > +>; + +export type BuildSetMaxTxGasLimitReturnType = PrepareTransactionRequestReturnTypeWithChainId; + +export async function buildSetMaxTxGasLimit( + client: PublicClient, + { account, upgradeExecutor, params }: BuildSetMaxTxGasLimitParameters, +): Promise { + const validatedPublicClient = validateChildChainPublicClient(client); + + const request = await client.prepareTransactionRequest({ + chain: client.chain as Chain | undefined, + account, + ...prepareUpgradeExecutorCallParameters({ + to: arbOwnerAddress, + upgradeExecutor, + args: [params.limit], + abi: arbOwnerABI, + functionName: 'setMaxTxGasLimit', + }), + } satisfies PrepareTransactionRequestParameters); + + return { ...request, chainId: validatedPublicClient.chain.id }; +} diff --git a/src/actions/buildSetParentPricePerUnit.ts b/src/actions/buildSetParentPricePerUnit.ts new file mode 100644 index 00000000..d09b0441 --- /dev/null +++ b/src/actions/buildSetParentPricePerUnit.ts @@ -0,0 +1,41 @@ +import { Chain, PrepareTransactionRequestParameters, PublicClient, Transport } from 'viem'; +import { arbOwnerABI, arbOwnerAddress } from '../contracts/ArbOwner'; +import { + PrepareTransactionRequestReturnTypeWithChainId, + WithAccount, + WithUpgradeExecutor, +} from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { prepareUpgradeExecutorCallParameters } from '../prepareUpgradeExecutorCallParameters'; +import { validateChildChainPublicClient } from '../types/validateChildChainPublicClient'; + +export type BuildSetParentPricePerUnitParameters = Prettify< + WithUpgradeExecutor< + WithAccount<{ + params: { pricePerUnit: bigint }; + }> + > +>; + +export type BuildSetParentPricePerUnitReturnType = PrepareTransactionRequestReturnTypeWithChainId; + +export async function buildSetParentPricePerUnit( + client: PublicClient, + { account, upgradeExecutor, params }: BuildSetParentPricePerUnitParameters, +): Promise { + const validatedPublicClient = validateChildChainPublicClient(client); + + const request = await client.prepareTransactionRequest({ + chain: validatedPublicClient.chain, + account, + ...prepareUpgradeExecutorCallParameters({ + to: arbOwnerAddress, + upgradeExecutor, + args: [params.pricePerUnit], + abi: arbOwnerABI, + functionName: 'setL1PricePerUnit', + }), + } satisfies PrepareTransactionRequestParameters); + + return { ...request, chainId: validatedPublicClient.chain.id }; +} diff --git a/src/actions/buildSetParentPricingRewardRate.ts b/src/actions/buildSetParentPricingRewardRate.ts new file mode 100644 index 00000000..89853f57 --- /dev/null +++ b/src/actions/buildSetParentPricingRewardRate.ts @@ -0,0 +1,42 @@ +import { Chain, PrepareTransactionRequestParameters, PublicClient, Transport } from 'viem'; +import { arbOwnerABI, arbOwnerAddress } from '../contracts/ArbOwner'; +import { + PrepareTransactionRequestReturnTypeWithChainId, + WithAccount, + WithUpgradeExecutor, +} from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { validateChildChainPublicClient } from '../types/validateChildChainPublicClient'; +import { prepareUpgradeExecutorCallParameters } from '../prepareUpgradeExecutorCallParameters'; + +export type BuildSetParentPricingRewardRateParameters = Prettify< + WithUpgradeExecutor< + WithAccount<{ + params: { weiPerUnit: bigint }; + }> + > +>; + +export type BuildSetParentPricingRewardRateReturnType = + PrepareTransactionRequestReturnTypeWithChainId; + +export async function buildSetParentPricingRewardRate( + client: PublicClient, + { account, upgradeExecutor, params }: BuildSetParentPricingRewardRateParameters, +): Promise { + const validatedPublicClient = validateChildChainPublicClient(client); + + const request = await client.prepareTransactionRequest({ + chain: client.chain, + account, + ...prepareUpgradeExecutorCallParameters({ + to: arbOwnerAddress, + upgradeExecutor, + args: [params.weiPerUnit], + abi: arbOwnerABI, + functionName: 'setL1PricingRewardRate', + }), + } satisfies PrepareTransactionRequestParameters); + + return { ...request, chainId: validatedPublicClient.chain.id }; +} diff --git a/src/actions/buildSetParentPricingRewardRecipient.ts b/src/actions/buildSetParentPricingRewardRecipient.ts new file mode 100644 index 00000000..d5f79a10 --- /dev/null +++ b/src/actions/buildSetParentPricingRewardRecipient.ts @@ -0,0 +1,42 @@ +import { Address, Chain, PrepareTransactionRequestParameters, PublicClient, Transport } from 'viem'; +import { arbOwnerABI, arbOwnerAddress } from '../contracts/ArbOwner'; +import { + PrepareTransactionRequestReturnTypeWithChainId, + WithAccount, + WithUpgradeExecutor, +} from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { validateChildChainPublicClient } from '../types/validateChildChainPublicClient'; +import { prepareUpgradeExecutorCallParameters } from '../prepareUpgradeExecutorCallParameters'; + +export type BuildSetParentPricingRewardRecipientParameters = Prettify< + WithUpgradeExecutor< + WithAccount<{ + params: { recipient: Address }; + }> + > +>; + +export type BuildSetParentPricingRewardRecipientReturnType = + PrepareTransactionRequestReturnTypeWithChainId; + +export async function buildSetParentPricingRewardRecipient( + client: PublicClient, + { account, upgradeExecutor, params }: BuildSetParentPricingRewardRecipientParameters, +): Promise { + const validatedPublicClient = validateChildChainPublicClient(client); + + const request = await client.prepareTransactionRequest({ + chain: client.chain, + account, + ...prepareUpgradeExecutorCallParameters({ + to: arbOwnerAddress, + upgradeExecutor, + args: [params.recipient], + abi: arbOwnerABI, + functionName: 'setL1PricingRewardRecipient', + }), + } satisfies PrepareTransactionRequestParameters); + + return { ...request, chainId: validatedPublicClient.chain.id }; +} diff --git a/src/actions/buildSetSpeedLimit.ts b/src/actions/buildSetSpeedLimit.ts new file mode 100644 index 00000000..c01a11a8 --- /dev/null +++ b/src/actions/buildSetSpeedLimit.ts @@ -0,0 +1,41 @@ +import { Chain, PrepareTransactionRequestParameters, PublicClient, Transport } from 'viem'; +import { arbOwnerABI, arbOwnerAddress } from '../contracts/ArbOwner'; +import { + PrepareTransactionRequestReturnTypeWithChainId, + WithAccount, + WithUpgradeExecutor, +} from '../types/Actions'; +import { Prettify } from '../types/utils'; +import { prepareUpgradeExecutorCallParameters } from '../prepareUpgradeExecutorCallParameters'; +import { validateChildChainPublicClient } from '../types/validateChildChainPublicClient'; + +export type BuildSetSpeedLimitParameters = Prettify< + WithUpgradeExecutor< + WithAccount<{ + params: { limit: bigint }; + }> + > +>; + +export type BuildSetSpeedLimitReturnType = PrepareTransactionRequestReturnTypeWithChainId; + +export async function buildSetSpeedLimit( + client: PublicClient, + { account, upgradeExecutor, params }: BuildSetSpeedLimitParameters, +): Promise { + const validatedPublicClient = validateChildChainPublicClient(client); + + const request = await client.prepareTransactionRequest({ + chain: client.chain, + account, + ...prepareUpgradeExecutorCallParameters({ + to: arbOwnerAddress, + upgradeExecutor, + args: [params.limit], + abi: arbOwnerABI, + functionName: 'setSpeedLimit', + }), + } satisfies PrepareTransactionRequestParameters); + + return { ...request, chainId: validatedPublicClient.chain.id }; +} diff --git a/src/types/validateChildChainPublicClient.ts b/src/types/validateChildChainPublicClient.ts new file mode 100644 index 00000000..dc8be6d2 --- /dev/null +++ b/src/types/validateChildChainPublicClient.ts @@ -0,0 +1,16 @@ +import { Chain, PublicClient, Transport } from 'viem'; +import { Prettify } from './utils'; + +export type ChildChainPublicClient = Prettify< + PublicClient & { chain: NonNullable } +>; + +export function validateChildChainPublicClient( + publicClient: PublicClient, +): ChildChainPublicClient { + if (!publicClient.chain) { + throw new Error('client.chain is undefined'); + } + + return publicClient as ChildChainPublicClient; +} From 53e6638cbcc545563f17cf0109d6483be2632aa4 Mon Sep 17 00:00:00 2001 From: Christophe Date: Fri, 28 Jun 2024 12:54:27 +0000 Subject: [PATCH 2/5] Feat: Add v1 ArbOwnerPublic getters --- src/actions/getAllChainOwners.ts | 19 +++++++++++++++++++ src/actions/getInfraFeeAccount.ts | 19 +++++++++++++++++++ src/actions/getNetworkFeeAccount.ts | 19 +++++++++++++++++++ src/actions/getScheduledUpgrade.ts | 27 +++++++++++++++++++++++++++ src/actions/isChainOwner.ts | 23 +++++++++++++++++++++++ 5 files changed, 107 insertions(+) create mode 100644 src/actions/getAllChainOwners.ts create mode 100644 src/actions/getInfraFeeAccount.ts create mode 100644 src/actions/getNetworkFeeAccount.ts create mode 100644 src/actions/getScheduledUpgrade.ts create mode 100644 src/actions/isChainOwner.ts diff --git a/src/actions/getAllChainOwners.ts b/src/actions/getAllChainOwners.ts new file mode 100644 index 00000000..6c07a098 --- /dev/null +++ b/src/actions/getAllChainOwners.ts @@ -0,0 +1,19 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbOwnerPublicABI, arbOwnerPublicAddress } from '../contracts/ArbOwnerPublic'; + +export type GetAllChainOwnersParameters = void; + +export type GetAllChainOwnersReturnType = ReadContractReturnType< + typeof arbOwnerPublicABI, + 'getAllChainOwners' +>; + +export async function getAllChainOwners( + client: PublicClient, +): Promise { + return client.readContract({ + abi: arbOwnerPublicABI, + functionName: 'getAllChainOwners', + address: arbOwnerPublicAddress, + }); +} diff --git a/src/actions/getInfraFeeAccount.ts b/src/actions/getInfraFeeAccount.ts new file mode 100644 index 00000000..53a09f0f --- /dev/null +++ b/src/actions/getInfraFeeAccount.ts @@ -0,0 +1,19 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbOwnerPublicABI, arbOwnerPublicAddress } from '../contracts/ArbOwnerPublic'; + +export type GetInfraFeeAccountParameters = void; + +export type GetInfraFeeAccountReturnType = ReadContractReturnType< + typeof arbOwnerPublicABI, + 'getInfraFeeAccount' +>; + +export async function getInfraFeeAccount( + client: PublicClient, +): Promise { + return client.readContract({ + abi: arbOwnerPublicABI, + functionName: 'getInfraFeeAccount', + address: arbOwnerPublicAddress, + }); +} diff --git a/src/actions/getNetworkFeeAccount.ts b/src/actions/getNetworkFeeAccount.ts new file mode 100644 index 00000000..d1d2d6ef --- /dev/null +++ b/src/actions/getNetworkFeeAccount.ts @@ -0,0 +1,19 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbOwnerPublicABI, arbOwnerPublicAddress } from '../contracts/ArbOwnerPublic'; + +export type GetNetworkFeeAccountParameters = void; + +export type GetNetworkFeeAccountReturnType = ReadContractReturnType< + typeof arbOwnerPublicABI, + 'getNetworkFeeAccount' +>; + +export async function getNetworkFeeAccount( + client: PublicClient, +): Promise { + return client.readContract({ + abi: arbOwnerPublicABI, + functionName: 'getNetworkFeeAccount', + address: arbOwnerPublicAddress, + }); +} diff --git a/src/actions/getScheduledUpgrade.ts b/src/actions/getScheduledUpgrade.ts new file mode 100644 index 00000000..97cb591c --- /dev/null +++ b/src/actions/getScheduledUpgrade.ts @@ -0,0 +1,27 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbOwnerPublicABI, arbOwnerPublicAddress } from '../contracts/ArbOwnerPublic'; + +export type GetScheduledUpgradeParameters = void; + +type GetScheduledUpgradeRawReturnType = ReadContractReturnType< + typeof arbOwnerPublicABI, + 'getScheduledUpgrade' +>; +export type GetScheduledUpgradeReturnType = { + arbosVersion: GetScheduledUpgradeRawReturnType[0]; + scheduledForTimestamp: GetScheduledUpgradeRawReturnType[1]; +}; + +export async function getScheduledUpgrade( + client: PublicClient, +): Promise { + const [arbosVersion, scheduledForTimestamp] = await client.readContract({ + abi: arbOwnerPublicABI, + functionName: 'getScheduledUpgrade', + address: arbOwnerPublicAddress, + }); + return { + arbosVersion, + scheduledForTimestamp, + }; +} diff --git a/src/actions/isChainOwner.ts b/src/actions/isChainOwner.ts new file mode 100644 index 00000000..5ed2918e --- /dev/null +++ b/src/actions/isChainOwner.ts @@ -0,0 +1,23 @@ +import { Address, Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbOwnerPublicABI, arbOwnerPublicAddress } from '../contracts/ArbOwnerPublic'; + +export type IsChainOwnerParameters = { + address: Address; +}; + +export type IsChainOwnerReturnType = ReadContractReturnType< + typeof arbOwnerPublicABI, + 'isChainOwner' +>; + +export async function isChainOwner( + client: PublicClient, + args: IsChainOwnerParameters, +): Promise { + return client.readContract({ + abi: arbOwnerPublicABI, + functionName: 'isChainOwner', + address: arbOwnerPublicAddress, + args: [args.address], + }); +} From 7f20a37bafe805a069e3ddcea6650f7ad54c452e Mon Sep 17 00:00:00 2001 From: Christophe Date: Fri, 28 Jun 2024 15:05:11 +0000 Subject: [PATCH 3/5] Feat: Add v1 ArbGasInfo getters --- src/actions/getGasAccountingParams.ts | 27 +++++++++++++++++++++++++ src/actions/getMinimumGasPrice.ts | 19 +++++++++++++++++ src/actions/getParentBaseFeeEstimate.ts | 19 +++++++++++++++++ src/actions/getParentRewardRate.ts | 19 +++++++++++++++++ src/actions/getParentRewardRecipient.ts | 19 +++++++++++++++++ 5 files changed, 103 insertions(+) create mode 100644 src/actions/getGasAccountingParams.ts create mode 100644 src/actions/getMinimumGasPrice.ts create mode 100644 src/actions/getParentBaseFeeEstimate.ts create mode 100644 src/actions/getParentRewardRate.ts create mode 100644 src/actions/getParentRewardRecipient.ts diff --git a/src/actions/getGasAccountingParams.ts b/src/actions/getGasAccountingParams.ts new file mode 100644 index 00000000..a6b97118 --- /dev/null +++ b/src/actions/getGasAccountingParams.ts @@ -0,0 +1,27 @@ +import { Chain, PublicClient, Transport } from 'viem'; +import { arbGasInfoABI, arbGasInfoAddress } from '../contracts/ArbGasInfo'; + +export type GetGasAccountingParamsParameters = void; + +export type GetGasAccountingParamsReturnType = { + speedLimitPerSecond: bigint; + gasPoolMax: bigint; + maxTxGasLimit: bigint; +}; + +export async function getGasAccountingParams( + client: PublicClient, +): Promise { + // `gasPoolMax` is always zero, as the exponential pricing model has no such notion. + // see https://github.com/OffchainLabs/nitro-contracts/blob/main/src/precompiles/ArbGasInfo.sol + const [speedLimitPerSecond, gasPoolMax, maxTxGasLimit] = await client.readContract({ + abi: arbGasInfoABI, + functionName: 'getGasAccountingParams', + address: arbGasInfoAddress, + }); + return { + speedLimitPerSecond, + gasPoolMax, + maxTxGasLimit, + }; +} diff --git a/src/actions/getMinimumGasPrice.ts b/src/actions/getMinimumGasPrice.ts new file mode 100644 index 00000000..99d11273 --- /dev/null +++ b/src/actions/getMinimumGasPrice.ts @@ -0,0 +1,19 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbGasInfoABI, arbGasInfoAddress } from '../contracts/ArbGasInfo'; + +export type GetMinimumGasPriceParameters = void; + +export type GetMinimumGasPriceReturnType = ReadContractReturnType< + typeof arbGasInfoABI, + 'getMinimumGasPrice' +>; + +export async function getMinimumGasPrice( + client: PublicClient, +): Promise { + return client.readContract({ + abi: arbGasInfoABI, + functionName: 'getMinimumGasPrice', + address: arbGasInfoAddress, + }); +} diff --git a/src/actions/getParentBaseFeeEstimate.ts b/src/actions/getParentBaseFeeEstimate.ts new file mode 100644 index 00000000..bb3774e4 --- /dev/null +++ b/src/actions/getParentBaseFeeEstimate.ts @@ -0,0 +1,19 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbGasInfoABI, arbGasInfoAddress } from '../contracts/ArbGasInfo'; + +export type GetParentBaseFeeEstimateParameters = void; + +export type GetParentBaseFeeEstimateReturnType = ReadContractReturnType< + typeof arbGasInfoABI, + 'getL1BaseFeeEstimate' +>; + +export async function getParentBaseFeeEstimate( + client: PublicClient, +): Promise { + return client.readContract({ + abi: arbGasInfoABI, + functionName: 'getL1BaseFeeEstimate', + address: arbGasInfoAddress, + }); +} diff --git a/src/actions/getParentRewardRate.ts b/src/actions/getParentRewardRate.ts new file mode 100644 index 00000000..39b697ce --- /dev/null +++ b/src/actions/getParentRewardRate.ts @@ -0,0 +1,19 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbGasInfoABI, arbGasInfoAddress } from '../contracts/ArbGasInfo'; + +export type GetParentRewardRateParameters = void; + +export type GetParentRewardRateReturnType = ReadContractReturnType< + typeof arbGasInfoABI, + 'getL1RewardRate' +>; + +export async function getParentRewardRate( + client: PublicClient, +): Promise { + return client.readContract({ + abi: arbGasInfoABI, + functionName: 'getL1RewardRate', + address: arbGasInfoAddress, + }); +} diff --git a/src/actions/getParentRewardRecipient.ts b/src/actions/getParentRewardRecipient.ts new file mode 100644 index 00000000..39c440be --- /dev/null +++ b/src/actions/getParentRewardRecipient.ts @@ -0,0 +1,19 @@ +import { Chain, PublicClient, ReadContractReturnType, Transport } from 'viem'; +import { arbGasInfoABI, arbGasInfoAddress } from '../contracts/ArbGasInfo'; + +export type GetParentRewardRecipientParameters = void; + +export type GetParentRewardRecipientReturnType = ReadContractReturnType< + typeof arbGasInfoABI, + 'getL1RewardRecipient' +>; + +export async function getParentRewardRecipient( + client: PublicClient, +): Promise { + return client.readContract({ + abi: arbGasInfoABI, + functionName: 'getL1RewardRecipient', + address: arbGasInfoAddress, + }); +} From 7abce7418eec9f190ec5423a4ce8282754611ece Mon Sep 17 00:00:00 2001 From: Christophe Date: Tue, 24 Sep 2024 19:45:12 +0200 Subject: [PATCH 4/5] test: Add integration tests for arbOwner --- src/actions/arbOwner.integration.test.ts | 214 +++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 src/actions/arbOwner.integration.test.ts diff --git a/src/actions/arbOwner.integration.test.ts b/src/actions/arbOwner.integration.test.ts new file mode 100644 index 00000000..04fb028a --- /dev/null +++ b/src/actions/arbOwner.integration.test.ts @@ -0,0 +1,214 @@ +import { describe, it, expect } from 'vitest'; +import { getNitroTestnodePrivateKeyAccounts } from '../testHelpers'; +import { Address, createPublicClient, http, zeroAddress } from 'viem'; +import { nitroTestnodeL3 } from '../chains'; +import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; +import { getAllChainOwners } from './getAllChainOwners'; +import { buildAddChainOwner } from './buildAddChainOwner'; +import { buildRemoveChainOwner } from './buildRemoveChainOwner'; +import { isChainOwner } from './isChainOwner'; +import { getInfraFeeAccount } from './getInfraFeeAccount'; +import { getNetworkFeeAccount } from './getNetworkFeeAccount'; +import { getScheduledUpgrade } from './getScheduledUpgrade'; +import { buildSetMaxTxGasLimit } from './buildSetMaxTxGasLimit'; +import { buildSetSpeedLimit } from './buildSetSpeedLimit'; +import { buildSetParentPricePerUnit } from './buildSetParentPricePerUnit'; +import { getParentBaseFeeEstimate } from './getParentBaseFeeEstimate'; +import { getGasAccountingParams } from './getGasAccountingParams'; +import { buildSetParentPricingRewardRate } from './buildSetParentPricingRewardRate'; +import { getParentRewardRate } from './getParentRewardRate'; +import { buildSetParentPricingRewardRecipient } from './buildSetParentPricingRewardRecipient'; +import { getParentRewardRecipient } from './getParentRewardRecipient'; + +const { l3RollupOwner } = getNitroTestnodePrivateKeyAccounts(); + +const client = createPublicClient({ + chain: nitroTestnodeL3, + transport: http(), +}); + +describe('chain owner management', () => { + it('buildAdd/RemoveChainOwner successfully add and remove chain owner', async () => { + const randomAddress = privateKeyToAccount(generatePrivateKey()).address; + expect(await getAllChainOwners(client)).toEqual([l3RollupOwner.address]); + expect(await isChainOwner(client, { address: randomAddress })).toBeFalsy(); + + const addTransactionRequest = await buildAddChainOwner(client, { + upgradeExecutor: false, + account: l3RollupOwner.address, + params: { + newOwner: randomAddress, + }, + }); + const addTxHash = await client.sendRawTransaction({ + serializedTransaction: await l3RollupOwner.signTransaction(addTransactionRequest), + }); + await client.waitForTransactionReceipt({ hash: addTxHash }); + + expect(await isChainOwner(client, { address: randomAddress })).toBeTruthy(); + expect(await getAllChainOwners(client)).toEqual([l3RollupOwner.address, randomAddress]); + + const removeTransactionRequest = await buildRemoveChainOwner(client, { + upgradeExecutor: false, + account: l3RollupOwner.address, + params: { + owner: randomAddress, + }, + }); + const removeTxHash = await client.sendRawTransaction({ + serializedTransaction: await l3RollupOwner.signTransaction(removeTransactionRequest), + }); + await client.waitForTransactionReceipt({ hash: removeTxHash }); + + expect(await getAllChainOwners(client)).toEqual([l3RollupOwner.address]); + expect(await isChainOwner(client, { address: randomAddress })).toBeFalsy(); + }); +}); + +describe('Fee account', () => { + it('getInfraFeeAccount returns the infra fee account', async () => { + const infraFeeAccount = await getInfraFeeAccount(client); + expect(infraFeeAccount).toBe(zeroAddress); + }); + + it('getNetworkFeeAccount returns the network fee account', async () => { + const networkFeeAccount = await getNetworkFeeAccount(client); + expect(networkFeeAccount).toBe(l3RollupOwner.address); + }); +}); + +describe('Fee management', () => { + it('buildSetMaxTxGasLimit successfully set max gas limit for transaction', async () => { + async function changeMaxTxGasLimit(limit: bigint) { + const transactionRequest = await buildSetMaxTxGasLimit(client, { + upgradeExecutor: false, + account: l3RollupOwner.address, + params: { + limit, + }, + }); + const txHash = await client.sendRawTransaction({ + serializedTransaction: await l3RollupOwner.signTransaction(transactionRequest), + }); + await client.waitForTransactionReceipt({ hash: txHash }); + } + // const { maxTxGasLimit } = await getGasAccountingParams(client); + // expect(maxTxGasLimit).toEqual(32000000n) + + await changeMaxTxGasLimit(64_000_000n); + + // const { maxTxGasLimit } = await getGasAccountingParams(client); + // expect(maxTxGasLimit).toEqual(64000000n) + + await changeMaxTxGasLimit(32_000_000n); + + // const { maxTxGasLimit } = await getGasAccountingParams(client); + // expect(maxTxGasLimit).toEqual(32000000n) + }); + + it('buildSetSpeedLimit successfully speed limit', async () => { + async function changeSpeedLimit(limit: bigint) { + const transactionRequest = await buildSetSpeedLimit(client, { + upgradeExecutor: false, + account: l3RollupOwner.address, + params: { + limit, + }, + }); + const txHash = await client.sendRawTransaction({ + serializedTransaction: await l3RollupOwner.signTransaction(transactionRequest), + }); + await client.waitForTransactionReceipt({ hash: txHash }); + } + expect((await getGasAccountingParams(client)).speedLimitPerSecond).toEqual(7_000_000n); + + await changeSpeedLimit(14_000_000n); + expect((await getGasAccountingParams(client)).speedLimitPerSecond).toEqual(14_000_000n); + + await changeSpeedLimit(7_000_000n); + expect((await getGasAccountingParams(client)).speedLimitPerSecond).toEqual(7_000_000n); + }); + + it('buildSetParentPricePerUnit successfully set parent price per unit', async () => { + async function changeParentPricePerUnit(pricePerUnit: bigint) { + const transactionRequest = await buildSetParentPricePerUnit(client, { + upgradeExecutor: false, + account: l3RollupOwner.address, + params: { + pricePerUnit, + }, + }); + const txHash = await client.sendRawTransaction({ + serializedTransaction: await l3RollupOwner.signTransaction(transactionRequest), + }); + await client.waitForTransactionReceipt({ hash: txHash }); + } + + const initialParentBaseFeeEstimate = await getParentBaseFeeEstimate(client); + + await changeParentPricePerUnit(100_000_000n); + expect(await getParentBaseFeeEstimate(client)).toEqual(100_000_000n); + + await changeParentPricePerUnit(initialParentBaseFeeEstimate); + expect(await getParentBaseFeeEstimate(client)).toEqual(initialParentBaseFeeEstimate); + }); + + it('buildSetParentPricingRewardRate successfully set parent pricing reward rate', async () => { + async function changeParentPriceRewardRate(weiPerUnit: bigint) { + const transactionRequest = await buildSetParentPricingRewardRate(client, { + upgradeExecutor: false, + account: l3RollupOwner.address, + params: { + weiPerUnit, + }, + }); + const txHash = await client.sendRawTransaction({ + serializedTransaction: await l3RollupOwner.signTransaction(transactionRequest), + }); + await client.waitForTransactionReceipt({ hash: txHash }); + } + + const initialParentPriceRewardRate = await getParentRewardRate(client); + + await changeParentPriceRewardRate(200_000_000n); + expect(await getParentRewardRate(client)).toEqual(200_000_000n); + + await changeParentPriceRewardRate(initialParentPriceRewardRate); + expect(await getParentRewardRate(client)).toEqual(initialParentPriceRewardRate); + }); + + it('buildSetParentPricingRewardRecipient successfully set parent pricing reward recipient', async () => { + async function changeParentPriceRewardRecipient(recipient: Address) { + const transactionRequest = await buildSetParentPricingRewardRecipient(client, { + upgradeExecutor: false, + account: l3RollupOwner.address, + params: { + recipient, + }, + }); + const txHash = await client.sendRawTransaction({ + serializedTransaction: await l3RollupOwner.signTransaction(transactionRequest), + }); + await client.waitForTransactionReceipt({ hash: txHash }); + } + + const initialParentPriceRewardRecipient = await getParentRewardRecipient(client); + expect(initialParentPriceRewardRecipient).toEqual(l3RollupOwner.address); + + const randomAddress = privateKeyToAccount(generatePrivateKey()).address; + await changeParentPriceRewardRecipient(randomAddress); + expect(await getParentRewardRecipient(client)).toEqual(randomAddress); + + await changeParentPriceRewardRecipient(initialParentPriceRewardRecipient); + expect(await getParentRewardRecipient(client)).toEqual(initialParentPriceRewardRecipient); + }); +}); + +describe('GetScheduledUpgrade', () => { + it('getScheduledUpgrade returns timestamp and version for next upgrade', async () => { + expect(await getScheduledUpgrade(client)).toEqual({ + arbosVersion: 0n, + scheduledForTimestamp: 0n, + }); + }); +}); From 4c39805d0be60ec6dd44e8ad983d6a52e03bc98e Mon Sep 17 00:00:00 2001 From: Christophe Date: Fri, 27 Sep 2024 18:45:24 +0200 Subject: [PATCH 5/5] Fix test --- src/actions/arbOwner.integration.test.ts | 33 +++++++++++------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/actions/arbOwner.integration.test.ts b/src/actions/arbOwner.integration.test.ts index 04fb028a..9317873b 100644 --- a/src/actions/arbOwner.integration.test.ts +++ b/src/actions/arbOwner.integration.test.ts @@ -27,14 +27,16 @@ const client = createPublicClient({ transport: http(), }); +let l3UpgradeExecutorAddress: Address = '0x24198F8A339cd3C47AEa3A764A20d2dDaB4D1b5b'; + describe('chain owner management', () => { it('buildAdd/RemoveChainOwner successfully add and remove chain owner', async () => { const randomAddress = privateKeyToAccount(generatePrivateKey()).address; - expect(await getAllChainOwners(client)).toEqual([l3RollupOwner.address]); + expect(await getAllChainOwners(client)).toEqual([l3UpgradeExecutorAddress]); expect(await isChainOwner(client, { address: randomAddress })).toBeFalsy(); const addTransactionRequest = await buildAddChainOwner(client, { - upgradeExecutor: false, + upgradeExecutor: l3UpgradeExecutorAddress, account: l3RollupOwner.address, params: { newOwner: randomAddress, @@ -46,10 +48,10 @@ describe('chain owner management', () => { await client.waitForTransactionReceipt({ hash: addTxHash }); expect(await isChainOwner(client, { address: randomAddress })).toBeTruthy(); - expect(await getAllChainOwners(client)).toEqual([l3RollupOwner.address, randomAddress]); + expect(await getAllChainOwners(client)).toEqual([l3UpgradeExecutorAddress, randomAddress]); const removeTransactionRequest = await buildRemoveChainOwner(client, { - upgradeExecutor: false, + upgradeExecutor: l3UpgradeExecutorAddress, account: l3RollupOwner.address, params: { owner: randomAddress, @@ -60,7 +62,7 @@ describe('chain owner management', () => { }); await client.waitForTransactionReceipt({ hash: removeTxHash }); - expect(await getAllChainOwners(client)).toEqual([l3RollupOwner.address]); + expect(await getAllChainOwners(client)).toEqual([l3UpgradeExecutorAddress]); expect(await isChainOwner(client, { address: randomAddress })).toBeFalsy(); }); }); @@ -81,7 +83,7 @@ describe('Fee management', () => { it('buildSetMaxTxGasLimit successfully set max gas limit for transaction', async () => { async function changeMaxTxGasLimit(limit: bigint) { const transactionRequest = await buildSetMaxTxGasLimit(client, { - upgradeExecutor: false, + upgradeExecutor: l3UpgradeExecutorAddress, account: l3RollupOwner.address, params: { limit, @@ -92,24 +94,19 @@ describe('Fee management', () => { }); await client.waitForTransactionReceipt({ hash: txHash }); } - // const { maxTxGasLimit } = await getGasAccountingParams(client); - // expect(maxTxGasLimit).toEqual(32000000n) + expect((await getGasAccountingParams(client)).maxTxGasLimit).toEqual(32_000_000n); await changeMaxTxGasLimit(64_000_000n); - - // const { maxTxGasLimit } = await getGasAccountingParams(client); - // expect(maxTxGasLimit).toEqual(64000000n) + expect((await getGasAccountingParams(client)).maxTxGasLimit).toEqual(64_000_000n); await changeMaxTxGasLimit(32_000_000n); - - // const { maxTxGasLimit } = await getGasAccountingParams(client); - // expect(maxTxGasLimit).toEqual(32000000n) + expect((await getGasAccountingParams(client)).maxTxGasLimit).toEqual(32_000_000n); }); it('buildSetSpeedLimit successfully speed limit', async () => { async function changeSpeedLimit(limit: bigint) { const transactionRequest = await buildSetSpeedLimit(client, { - upgradeExecutor: false, + upgradeExecutor: l3UpgradeExecutorAddress, account: l3RollupOwner.address, params: { limit, @@ -132,7 +129,7 @@ describe('Fee management', () => { it('buildSetParentPricePerUnit successfully set parent price per unit', async () => { async function changeParentPricePerUnit(pricePerUnit: bigint) { const transactionRequest = await buildSetParentPricePerUnit(client, { - upgradeExecutor: false, + upgradeExecutor: l3UpgradeExecutorAddress, account: l3RollupOwner.address, params: { pricePerUnit, @@ -156,7 +153,7 @@ describe('Fee management', () => { it('buildSetParentPricingRewardRate successfully set parent pricing reward rate', async () => { async function changeParentPriceRewardRate(weiPerUnit: bigint) { const transactionRequest = await buildSetParentPricingRewardRate(client, { - upgradeExecutor: false, + upgradeExecutor: l3UpgradeExecutorAddress, account: l3RollupOwner.address, params: { weiPerUnit, @@ -180,7 +177,7 @@ describe('Fee management', () => { it('buildSetParentPricingRewardRecipient successfully set parent pricing reward recipient', async () => { async function changeParentPriceRewardRecipient(recipient: Address) { const transactionRequest = await buildSetParentPricingRewardRecipient(client, { - upgradeExecutor: false, + upgradeExecutor: l3UpgradeExecutorAddress, account: l3RollupOwner.address, params: { recipient,