Skip to content

Commit 311d549

Browse files
committed
feat: fix and add tests
1 parent d19a234 commit 311d549

File tree

3 files changed

+94
-56
lines changed

3 files changed

+94
-56
lines changed

v-next/hardhat/src/internal/builtin-plugins/network-manager/network-manager.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,10 @@ export class NetworkManagerImplementation implements NetworkManager {
121121
HardhatError.ERRORS.NETWORK.INVALID_CONFIG_OVERRIDE,
122122
{
123123
errors: `\t${validationErrors
124-
.map(
125-
(error) =>
126-
`* Error in ${error.path.join(".")}: ${error.message}`,
124+
.map((error) =>
125+
error.path.length > 0
126+
? `* Error in ${error.path.join(".")}: ${error.message}`
127+
: `* ${error.message}`,
127128
)
128129
.join("\n\t")}`,
129130
},

v-next/hardhat/src/internal/builtin-plugins/network-manager/type-validation.ts

+65-50
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type {
55
NetworkUserConfig,
66
} from "../../../types/config.js";
77
import type { HardhatUserConfigValidationError } from "../../../types/hooks.js";
8+
import type { RefinementCtx } from "zod";
89

910
import {
1011
getUnprefixedHexString,
@@ -211,71 +212,85 @@ const edrNetworkUserConfigSchema = z.object({
211212
throwOnTransactionFailures: z.optional(z.boolean()),
212213
});
213214

214-
const networkUserConfigSchema = z
215-
.discriminatedUnion("type", [
216-
httpNetworkUserConfigSchema,
217-
edrNetworkUserConfigSchema,
218-
])
219-
// The superRefine is used to perform additional validation of correlated
220-
// fields of the edr network that are not possible to express with Zod's
221-
// built-in validation methods.
222-
// Ideally, it should be applied to the edrNetworkUserConfigSchema, but it
223-
// returns a ZodEffects, which is not compatible with the discriminatedUnion
224-
// method, so it is applied to the networkUserConfigSchema instead.
225-
.superRefine((networkConfig, ctx) => {
226-
if (networkConfig.type === "edr") {
227-
const {
228-
hardfork = LATEST_HARDFORK,
229-
minGasPrice,
230-
initialBaseFeePerGas,
231-
enableTransientStorage,
232-
} = networkConfig;
233-
234-
if (hardforkGte(hardfork, HardforkName.LONDON)) {
235-
if (minGasPrice !== undefined) {
236-
ctx.addIssue({
237-
code: z.ZodIssueCode.custom,
238-
message:
239-
"minGasPrice is not valid for networks with EIP-1559. Try an older hardfork or remove it.",
240-
});
241-
}
242-
} else {
243-
if (initialBaseFeePerGas !== undefined) {
244-
ctx.addIssue({
245-
code: z.ZodIssueCode.custom,
246-
message:
247-
"initialBaseFeePerGas is only valid for networks with EIP-1559. Try a newer hardfork or remove it.",
248-
});
249-
}
250-
}
251-
252-
if (
253-
!hardforkGte(hardfork, HardforkName.CANCUN) &&
254-
enableTransientStorage === true
255-
) {
215+
const baseNetworkUserConfigSchema = z.discriminatedUnion("type", [
216+
httpNetworkUserConfigSchema,
217+
edrNetworkUserConfigSchema,
218+
]);
219+
220+
function refineEdrNetworkUserConfig(
221+
networkConfig: z.infer<typeof baseNetworkUserConfigSchema>,
222+
ctx: RefinementCtx,
223+
): void {
224+
if (networkConfig.type === "edr") {
225+
const {
226+
hardfork = LATEST_HARDFORK,
227+
minGasPrice,
228+
initialBaseFeePerGas,
229+
enableTransientStorage,
230+
} = networkConfig;
231+
232+
if (hardforkGte(hardfork, HardforkName.LONDON)) {
233+
if (minGasPrice !== undefined) {
256234
ctx.addIssue({
257235
code: z.ZodIssueCode.custom,
258-
message: `'enableTransientStorage' is not supported for hardforks before 'cancun'. Please use a hardfork from 'cancun' onwards to enable this feature.`,
236+
message:
237+
"minGasPrice is not valid for networks with EIP-1559. Try an older hardfork or remove it.",
259238
});
260239
}
261-
if (
262-
hardforkGte(hardfork, HardforkName.CANCUN) &&
263-
enableTransientStorage === false
264-
) {
240+
} else {
241+
if (initialBaseFeePerGas !== undefined) {
265242
ctx.addIssue({
266243
code: z.ZodIssueCode.custom,
267-
message: `'enableTransientStorage' must be enabled for hardforks 'cancun' or later. To disable this feature, use a hardfork before 'cancun'.`,
244+
message:
245+
"initialBaseFeePerGas is only valid for networks with EIP-1559. Try a newer hardfork or remove it.",
268246
});
269247
}
270248
}
271-
});
249+
250+
if (
251+
!hardforkGte(hardfork, HardforkName.CANCUN) &&
252+
enableTransientStorage === true
253+
) {
254+
ctx.addIssue({
255+
code: z.ZodIssueCode.custom,
256+
message: `'enableTransientStorage' is not supported for hardforks before 'cancun'. Please use a hardfork from 'cancun' onwards to enable this feature.`,
257+
});
258+
}
259+
if (
260+
hardforkGte(hardfork, HardforkName.CANCUN) &&
261+
enableTransientStorage === false
262+
) {
263+
ctx.addIssue({
264+
code: z.ZodIssueCode.custom,
265+
message: `'enableTransientStorage' must be enabled for hardforks 'cancun' or later. To disable this feature, use a hardfork before 'cancun'.`,
266+
});
267+
}
268+
}
269+
}
270+
271+
// The superRefine is used to perform additional validation of correlated
272+
// fields of the edr network that are not possible to express with Zod's
273+
// built-in validation methods.
274+
// Ideally, it should be applied to the edrNetworkUserConfigSchema, but it
275+
// returns a ZodEffects, which is not compatible with the discriminatedUnion
276+
// method, so it is applied to the networkUserConfigSchema instead.
277+
const networkUserConfigSchema = baseNetworkUserConfigSchema.superRefine(
278+
refineEdrNetworkUserConfig,
279+
);
272280

273281
const userConfigSchema = z.object({
274282
defaultChainType: z.optional(chainTypeUserConfigSchema),
275283
defaultNetwork: z.optional(z.string()),
276284
networks: z.optional(z.record(networkUserConfigSchema)),
277285
});
278286

287+
const networkConfigOverrideSchema = z
288+
.discriminatedUnion("type", [
289+
httpNetworkUserConfigSchema.strict(),
290+
edrNetworkUserConfigSchema.strict(),
291+
])
292+
.superRefine(refineEdrNetworkUserConfig);
293+
279294
export async function validateNetworkUserConfig(
280295
userConfig: HardhatUserConfig,
281296
): Promise<HardhatUserConfigValidationError[]> {
@@ -287,7 +302,7 @@ export async function validateNetworkConfigOverride(
287302
): Promise<HardhatUserConfigValidationError[]> {
288303
return validateUserConfigZodType(
289304
networkConfigOverride,
290-
networkUserConfigSchema,
305+
networkConfigOverrideSchema,
291306
);
292307
}
293308

v-next/hardhat/test/internal/builtin-plugins/network-manager/network-manager.ts

+25-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import type {
55
NetworkConnection,
66
NetworkManager,
77
} from "../../../../src/types/network.js";
8-
import type { NetworkConfig } from "@ignored/hardhat-vnext/types/config";
8+
import type {
9+
HttpNetworkConfigOverride,
10+
NetworkConfig,
11+
} from "@ignored/hardhat-vnext/types/config";
912

1013
import assert from "node:assert/strict";
1114
import { before, describe, it } from "node:test";
@@ -112,16 +115,20 @@ describe("NetworkManagerImplementation", () => {
112115
});
113116

114117
it("should override the network's chain config with the specified chain config", async () => {
118+
const httpConfigOverride: HttpNetworkConfigOverride = {
119+
chainId: 1234,
120+
timeout: 30_000, // specific to http networks
121+
};
115122
const networkConnection = await networkManager.connect(
116123
"myNetwork",
117124
OPTIMISM_CHAIN_TYPE,
118-
{ chainId: 1234 },
125+
httpConfigOverride,
119126
);
120127
assert.equal(networkConnection.networkName, "myNetwork");
121128
assert.equal(networkConnection.chainType, OPTIMISM_CHAIN_TYPE);
122129
assert.deepEqual(networkConnection.networkConfig, {
123130
...networks.myNetwork,
124-
chainId: 1234,
131+
...httpConfigOverride,
125132
});
126133
});
127134

@@ -173,6 +180,21 @@ describe("NetworkManagerImplementation", () => {
173180
);
174181
});
175182

183+
it("should throw an error if the specified network config override has mixed properties from http and edr networks", async () => {
184+
await assertRejectsWithHardhatError(
185+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
186+
-- Cast to test validation error */
187+
networkManager.connect("myNetwork", OPTIMISM_CHAIN_TYPE, {
188+
url: "http://localhost:8545",
189+
hardfork: "cancun",
190+
} as any),
191+
HardhatError.ERRORS.NETWORK.INVALID_CONFIG_OVERRIDE,
192+
{
193+
errors: `\t* Unrecognized key(s) in object: 'hardfork'`,
194+
},
195+
);
196+
});
197+
176198
it("should throw an error if the specified chain type doesn't match the network's chain type", async () => {
177199
await assertRejectsWithHardhatError(
178200
networkManager.connect("myNetwork", L1_CHAIN_TYPE),

0 commit comments

Comments
 (0)