Skip to content

Commit e0b2ba9

Browse files
authored
Merge pull request #7096 from NomicFoundation/fix-viem-l2-actions
Fix hh-viem l2 actions when using the optimism chain type
2 parents 1f39fa9 + 9875011 commit e0b2ba9

File tree

5 files changed

+52
-38
lines changed

5 files changed

+52
-38
lines changed

.changeset/chilled-mails-call.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@nomicfoundation/hardhat-viem": patch
3+
---
4+
5+
Fixed hardhat-viem support for L2 actions when using the optimism chain type

v-next/hardhat-viem/src/internal/chains.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { TestClientMode } from "../types.js";
2+
import type { ChainType } from "hardhat/types/network";
23
import type { EthereumProvider } from "hardhat/types/providers";
34
import type { Chain as ViemChain } from "viem";
45

@@ -9,7 +10,7 @@ import {
910
import { isObject } from "@nomicfoundation/hardhat-utils/lang";
1011
import { extractChain } from "viem";
1112
import * as chainsModule from "viem/chains";
12-
import { hardhat, anvil } from "viem/chains";
13+
import { hardhat, anvil, optimism } from "viem/chains";
1314

1415
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
1516
-- TODO: this assertion should not be necessary */
@@ -23,7 +24,10 @@ const isAnvilNetworkCache = new WeakMap<EthereumProvider, boolean>();
2324
const HARDHAT_METADATA_METHOD = "hardhat_metadata";
2425
const ANVIL_NODE_INFO_METHOD = "anvil_nodeInfo";
2526

26-
export async function getChain(provider: EthereumProvider): Promise<ViemChain> {
27+
export async function getChain<ChainTypeT extends ChainType | string>(
28+
provider: EthereumProvider,
29+
chainType: ChainTypeT,
30+
): Promise<ViemChain> {
2731
const cachedChain = chainCache.get(provider);
2832
if (cachedChain !== undefined) {
2933
return cachedChain;
@@ -38,7 +42,7 @@ export async function getChain(provider: EthereumProvider): Promise<ViemChain> {
3842

3943
if ((await isDevelopmentNetwork(provider)) || chain === undefined) {
4044
if (await isHardhatNetwork(provider)) {
41-
chain = createHardhatChain(provider, chainId);
45+
chain = createHardhatChain(provider, chainId, chainType);
4246
} else if (await isAnvilNetwork(provider)) {
4347
chain = {
4448
...anvil,
@@ -155,9 +159,10 @@ async function isMethodSupported(provider: EthereumProvider, method: string) {
155159
}
156160
}
157161

158-
function createHardhatChain(
162+
function createHardhatChain<ChainTypeT extends ChainType | string>(
159163
provider: EthereumProvider,
160164
chainId: number,
165+
chainType: ChainTypeT,
161166
): ViemChain {
162167
const hardhatMetadata = hardhatMetadataCache.get(provider);
163168
assertHardhatInvariant(
@@ -180,10 +185,19 @@ function createHardhatChain(
180185
}
181186
}
182187

183-
return {
188+
const chain: ViemChain = {
184189
...hardhat,
185190
id: chainId,
186191
};
192+
193+
if (chainType === "optimism") {
194+
// we add the optimism contracts to enable viem's L2 actions
195+
chain.contracts = {
196+
...optimism.contracts,
197+
};
198+
}
199+
200+
return chain;
187201
}
188202

189203
interface HardhatMetadata {

v-next/hardhat-viem/src/internal/clients.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ export async function getPublicClient<ChainTypeT extends ChainType | string>(
2929
chainType: ChainTypeT,
3030
publicClientConfig?: Partial<ViemPublicClientConfig>,
3131
): Promise<GetPublicClientReturnType<ChainTypeT>> {
32-
const chain = publicClientConfig?.chain ?? (await getChain(provider));
32+
const chain =
33+
publicClientConfig?.chain ?? (await getChain(provider, chainType));
3334
const { defaultClientParams, defaultTransportParams } =
3435
await getDefaultParams(provider);
3536

@@ -54,7 +55,8 @@ export async function getWalletClients<ChainTypeT extends ChainType | string>(
5455
chainType: ChainTypeT,
5556
walletClientConfig?: Partial<ViemWalletClientConfig>,
5657
): Promise<Array<GetWalletClientReturnType<ChainTypeT>>> {
57-
const chain = walletClientConfig?.chain ?? (await getChain(provider));
58+
const chain =
59+
walletClientConfig?.chain ?? (await getChain(provider, chainType));
5860
const accounts = await getAccounts(provider);
5961
const { defaultClientParams, defaultTransportParams } =
6062
await getDefaultParams(provider);
@@ -86,7 +88,8 @@ export async function getWalletClient<ChainTypeT extends ChainType | string>(
8688
address: ViemAddress,
8789
walletClientConfig?: Partial<ViemWalletClientConfig>,
8890
): Promise<GetWalletClientReturnType<ChainTypeT>> {
89-
const chain = walletClientConfig?.chain ?? (await getChain(provider));
91+
const chain =
92+
walletClientConfig?.chain ?? (await getChain(provider, chainType));
9093
const { defaultClientParams, defaultTransportParams } =
9194
await getDefaultParams(provider);
9295

@@ -114,7 +117,8 @@ export async function getDefaultWalletClient<
114117
chainType: ChainTypeT,
115118
walletClientConfig?: Partial<ViemWalletClientConfig>,
116119
): Promise<GetWalletClientReturnType<ChainTypeT>> {
117-
const chain = walletClientConfig?.chain ?? (await getChain(provider));
120+
const chain =
121+
walletClientConfig?.chain ?? (await getChain(provider, chainType));
118122
const [defaultAccount] = await getAccounts(provider);
119123

120124
if (defaultAccount === undefined) {
@@ -139,7 +143,8 @@ export async function getTestClient<ChainTypeT extends ChainType | string>(
139143
chainType: ChainTypeT,
140144
testClientConfig?: Partial<ViemTestClientConfig>,
141145
): Promise<TestClient> {
142-
const chain = testClientConfig?.chain ?? (await getChain(provider));
146+
const chain =
147+
testClientConfig?.chain ?? (await getChain(provider, chainType));
143148
const mode = await getMode(provider);
144149

145150
const testClient = createTestClient({

v-next/hardhat-viem/test/chains.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ describe("chains", () => {
2121
it("should return the chain corresponding to the chain id", async () => {
2222
const provider = new MockEthereumProvider({ eth_chainId: "0x1" }); // mainnet chain id
2323

24-
const chain = await getChain(provider);
24+
const chain = await getChain(provider, "generic");
2525

2626
assert.deepEqual(chain, chains.mainnet);
2727
assert.equal(provider.callCount, 1);
@@ -33,7 +33,7 @@ describe("chains", () => {
3333
hardhat_metadata: {},
3434
});
3535

36-
const chain = await getChain(provider);
36+
const chain = await getChain(provider, "generic");
3737

3838
assert.deepEqual(chain, chains.hardhat);
3939
assert.equal(provider.callCount, 2);
@@ -49,7 +49,7 @@ describe("chains", () => {
4949
},
5050
});
5151

52-
const chain = await getChain(provider);
52+
const chain = await getChain(provider, "generic");
5353

5454
assert.deepEqual(chain, {
5555
...chains.mainnet,
@@ -69,7 +69,7 @@ describe("chains", () => {
6969
},
7070
});
7171

72-
const chain = await getChain(provider);
72+
const chain = await getChain(provider, "generic");
7373

7474
assert.deepEqual(chain, {
7575
...chains.hardhat,
@@ -84,7 +84,7 @@ describe("chains", () => {
8484
anvil_nodeInfo: {},
8585
});
8686

87-
const chain = await getChain(provider);
87+
const chain = await getChain(provider, "generic");
8888

8989
assert.deepEqual(chain, chains.anvil);
9090
assert.equal(provider.callCount, 2);
@@ -94,7 +94,7 @@ describe("chains", () => {
9494
const provider = new MockEthereumProvider({ eth_chainId: "0x0" }); // fake chain id 0
9595

9696
await assertRejectsWithHardhatError(
97-
getChain(provider),
97+
getChain(provider, "generic"),
9898
HardhatError.ERRORS.HARDHAT_VIEM.GENERAL.NETWORK_NOT_FOUND,
9999
{ chainId: 0 },
100100
);
@@ -104,7 +104,7 @@ describe("chains", () => {
104104
// chain id 999 corresponds to wanchainTestnet but also zoraTestnet
105105
const provider = new MockEthereumProvider({ eth_chainId: "0x3e7" }); // 999 in hex
106106

107-
const chainId = await getChain(provider);
107+
const chainId = await getChain(provider, "generic");
108108
assert.equal(chainId, chains.wanchainTestnet);
109109
});
110110

@@ -114,7 +114,7 @@ describe("chains", () => {
114114
hardhat_metadata: {},
115115
});
116116

117-
const chain = await getChain(provider);
117+
const chain = await getChain(provider, "generic");
118118

119119
assert.deepEqual(chain, {
120120
...chains.hardhat,
@@ -128,7 +128,7 @@ describe("chains", () => {
128128
anvil_nodeInfo: {},
129129
});
130130

131-
const chain = await getChain(provider);
131+
const chain = await getChain(provider, "generic");
132132

133133
assert.deepEqual(chain, {
134134
...chains.anvil,

v-next/hardhat-viem/test/clients.ts

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -497,38 +497,28 @@ describe("clients", () => {
497497
assert.equal(blockNumber, 1000000n);
498498
});
499499

500-
// TODO: this test is skipped because it forks optimism mainnet, which is slow
501-
it.skip("should be able to query the blockchain with the extended L2 actions", async () => {
500+
it("should have access to L2 actions", async () => {
502501
hre = await createHardhatRuntimeEnvironment({
503502
plugins: [HardhatViem],
504503
networks: {
505504
edrOptimism: {
506505
type: "edr",
507-
chainId: 10,
508506
chainType: "optimism",
509-
forking: {
510-
url: "https://mainnet.optimism.io",
511-
},
512-
gas: "auto",
513-
gasMultiplier: 1,
514-
gasPrice: "auto",
515507
},
516508
},
517509
});
518510

519-
const networkConnection = await hre.network.connect({
511+
const { viem } = await hre.network.connect({
520512
network: "edrOptimism",
521513
chainType: "optimism",
522514
});
523-
const publicClient = await networkConnection.viem.getPublicClient();
524-
const l1BaseFee = await publicClient.getL1BaseFee();
525-
const latestBlock = await publicClient.getBlock(); // should still have access to L1 actions
526-
527-
assert.ok(l1BaseFee > 0n, "L1 base fee should be greater than 0");
528-
assert.ok(
529-
latestBlock.number > 0n,
530-
"Latest block number should be greater than 0",
531-
);
515+
const publicClient = await viem.getPublicClient();
516+
const [senderClient] = await viem.getWalletClients();
517+
await publicClient.estimateL1Gas({
518+
account: senderClient.account.address,
519+
to: senderClient.account.address,
520+
value: 1n,
521+
});
532522
});
533523
});
534524
});

0 commit comments

Comments
 (0)