Skip to content

Commit 01c97fb

Browse files
authored
Merge pull request #8168 from NomicFoundation/plugin-from-resolution
Add `from` config tests and rename gas-config tests to network-config
2 parents c295c23 + e0af57c commit 01c97fb

3 files changed

Lines changed: 90 additions & 9 deletions

File tree

packages/hardhat-ethers/src/internal/signers/signers.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,10 @@ export class HardhatEthersSigner implements HardhatEthersSignerI {
252252

253253
const promises: Array<Promise<void>> = [];
254254

255-
// Make sure the from matches the sender
255+
// Mirror stock ethers: ENS-resolve `from` and assert it matches the
256+
// signer. Hardhat can be pointed at mainnet/testnets via --network, where
257+
// ENS works and users expect ethers-compatible `from` handling. Don't
258+
// "simplify" this by letting the node handle the mismatch.
256259
if (resolvedTx.from !== null && resolvedTx.from !== undefined) {
257260
const _from = resolvedTx.from;
258261
promises.push(

packages/hardhat-ethers/test/gas-config.ts renamed to packages/hardhat-ethers/test/network-config.ts

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ interface InitResult {
1616
networkConfig: NetworkConfig;
1717
}
1818

19-
describe("gas config behavior", () => {
19+
describe("network config behavior", () => {
2020
describe("in-process hardhat network", () => {
21-
defineGasConfigTests(() => initializeTestEthers(ARTIFACTS));
21+
defineNetworkConfigTests(() => initializeTestEthers(ARTIFACTS));
2222
});
2323

2424
describe("local http node", () => {
@@ -34,7 +34,7 @@ describe("gas config behavior", () => {
3434
await server.close();
3535
});
3636

37-
defineGasConfigTests(() =>
37+
defineNetworkConfigTests(() =>
3838
initializeTestEthers(ARTIFACTS, {
3939
networks: {
4040
localhost: { type: "http", url: `http://${address}:${port}` },
@@ -44,7 +44,7 @@ describe("gas config behavior", () => {
4444
});
4545
});
4646

47-
function defineGasConfigTests(initEthers: () => Promise<InitResult>) {
47+
function defineNetworkConfigTests(initEthers: () => Promise<InitResult>) {
4848
describe("gas: auto (default)", () => {
4949
let ethers: HardhatEthers;
5050

@@ -254,6 +254,48 @@ function defineGasConfigTests(initEthers: () => Promise<InitResult>) {
254254
});
255255
});
256256

257+
describe("from config", () => {
258+
let ethers: HardhatEthers;
259+
260+
before(async () => {
261+
({ ethers } = await initEthers());
262+
});
263+
264+
it("default signer sends from its own address", async () => {
265+
const [firstSigner, secondSigner] = await ethers.getSigners();
266+
const tx = await firstSigner.sendTransaction({ to: secondSigner });
267+
assert.equal(tx.from, firstSigner.address);
268+
});
269+
270+
it("non-first signer sends from its own address", async () => {
271+
const [firstSigner, secondSigner] = await ethers.getSigners();
272+
const tx = await secondSigner.sendTransaction({ to: firstSigner });
273+
assert.equal(tx.from, secondSigner.address);
274+
});
275+
276+
it("respects explicit from matching the signer", async () => {
277+
const [firstSigner, secondSigner] = await ethers.getSigners();
278+
const tx = await firstSigner.sendTransaction({
279+
to: secondSigner,
280+
from: firstSigner.address,
281+
});
282+
assert.equal(tx.from, firstSigner.address);
283+
});
284+
285+
it("throws when explicit from doesn't match the signer", async () => {
286+
const [firstSigner, secondSigner] = await ethers.getSigners();
287+
288+
// eslint-disable-next-line no-restricted-syntax -- it tests a non Hardhat error
289+
await assert.rejects(
290+
firstSigner.sendTransaction({
291+
to: firstSigner,
292+
from: secondSigner.address,
293+
}),
294+
/from address mismatch/,
295+
);
296+
});
297+
});
298+
257299
describe("non-interference with explicit gas-related calls", () => {
258300
let ethers: HardhatEthers;
259301
let provider: EthereumProvider;

packages/hardhat-viem/test/gas-config.ts renamed to packages/hardhat-viem/test/network-config.ts

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ interface InitResult {
1919
networkConfig: NetworkConfig;
2020
}
2121

22-
describe("gas config behavior", () => {
22+
describe("network config behavior", () => {
2323
useEphemeralFixtureProject("default-ts-project");
2424

2525
let hre: HardhatRuntimeEnvironment;
@@ -35,7 +35,7 @@ describe("gas config behavior", () => {
3535
});
3636

3737
describe("in-process hardhat network", () => {
38-
defineGasConfigTests(async () => {
38+
defineNetworkConfigTests(async () => {
3939
const conn = await hre.network.create();
4040
return {
4141
viem: conn.viem,
@@ -59,7 +59,7 @@ describe("gas config behavior", () => {
5959
await server.close();
6060
});
6161

62-
defineGasConfigTests(async () => {
62+
defineNetworkConfigTests(async () => {
6363
const conn = await hre.network.create({
6464
network: "localhost",
6565
override: { url: `http://${address}:${port}` },
@@ -73,7 +73,7 @@ describe("gas config behavior", () => {
7373
});
7474
});
7575

76-
function defineGasConfigTests(initViem: () => Promise<InitResult>) {
76+
function defineNetworkConfigTests(initViem: () => Promise<InitResult>) {
7777
describe("gas: auto (default)", () => {
7878
let viem: HardhatViemHelpers;
7979

@@ -367,6 +367,42 @@ function defineGasConfigTests(initViem: () => Promise<InitResult>) {
367367
});
368368
});
369369

370+
describe("from config", () => {
371+
let viem: HardhatViemHelpers;
372+
373+
before(async () => {
374+
({ viem } = await initViem());
375+
});
376+
377+
it("default wallet client sends from its own address", async () => {
378+
const publicClient = await viem.getPublicClient();
379+
const [firstClient, secondClient] = await viem.getWalletClients();
380+
const hash = await firstClient.sendTransaction({
381+
to: secondClient.account.address,
382+
value: 0n,
383+
});
384+
const tx = await publicClient.getTransaction({ hash });
385+
assert.equal(
386+
tx.from.toLowerCase(),
387+
firstClient.account.address.toLowerCase(),
388+
);
389+
});
390+
391+
it("non-first wallet client sends from its own address", async () => {
392+
const publicClient = await viem.getPublicClient();
393+
const [firstClient, secondClient] = await viem.getWalletClients();
394+
const hash = await secondClient.sendTransaction({
395+
to: firstClient.account.address,
396+
value: 0n,
397+
});
398+
const tx = await publicClient.getTransaction({ hash });
399+
assert.equal(
400+
tx.from.toLowerCase(),
401+
secondClient.account.address.toLowerCase(),
402+
);
403+
});
404+
});
405+
370406
describe("non-interference with RPC calls", () => {
371407
let viem: HardhatViemHelpers;
372408
let provider: EthereumProvider;

0 commit comments

Comments
 (0)