Skip to content

Commit 1d43aba

Browse files
committed
fix: use eth_maxPriorityFeePerGas for determing gas
Update `getFeeData` to match the `ethers` algorithm, specifically don't just assume `1_000_000_000n` as the `maxPriorityFeePerGas`. Instead call `eth_maxPriorityFeePerGas`, and only fall back to `1_000_000_000n` if there is no response. Fixes #5093
1 parent d35b919 commit 1d43aba

File tree

3 files changed

+93
-6
lines changed

3 files changed

+93
-6
lines changed

.changeset/smart-hotels-fold.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@nomicfoundation/hardhat-ethers": patch
3+
---
4+
5+
Use `eth_maxPriorityFeePerGas` for the max fee per gas calculation if available

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

+10-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,16 @@ export class HardhatEthersProvider implements ethers.Provider {
153153
const latestBlock = await this.getBlock("latest");
154154
const baseFeePerGas = latestBlock?.baseFeePerGas;
155155
if (baseFeePerGas !== undefined && baseFeePerGas !== null) {
156-
maxPriorityFeePerGas = 1_000_000_000n;
156+
try {
157+
maxPriorityFeePerGas = BigInt(
158+
await this._hardhatProvider.send("eth_maxPriorityFeePerGas")
159+
);
160+
} catch {
161+
// the max priority fee RPC call is not supported by
162+
// this chain
163+
}
164+
165+
maxPriorityFeePerGas = maxPriorityFeePerGas ?? 1_000_000_000n;
157166
maxFeePerGas = 2n * baseFeePerGas + maxPriorityFeePerGas;
158167
}
159168

packages/hardhat-ethers/test/hardhat-ethers-provider.ts

+78-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { assert, use } from "chai";
22
import chaiAsPromised from "chai-as-promised";
33

4+
import { EthereumProvider } from "hardhat/types/provider";
5+
import { HardhatEthersProvider } from "../src/internal/hardhat-ethers-provider";
46
import { ExampleContract, EXAMPLE_CONTRACT } from "./example-contracts";
57
import { usePersistentEnvironment } from "./environment";
68
import { assertIsNotNull, assertWithin } from "./helpers";
@@ -117,12 +119,83 @@ describe("hardhat ethers provider", function () {
117119
assert.strictEqual(network.chainId, 31337n);
118120
});
119121

120-
it("should return fee data", async function () {
121-
const feeData = await this.env.ethers.provider.getFeeData();
122+
describe("getFeeData", function () {
123+
it("should return fee data", async function () {
124+
const feeData = await this.env.ethers.provider.getFeeData();
122125

123-
assert.typeOf(feeData.gasPrice, "bigint");
124-
assert.typeOf(feeData.maxFeePerGas, "bigint");
125-
assert.typeOf(feeData.maxPriorityFeePerGas, "bigint");
126+
assert.typeOf(feeData.gasPrice, "bigint");
127+
assert.typeOf(feeData.maxFeePerGas, "bigint");
128+
assert.typeOf(feeData.maxPriorityFeePerGas, "bigint");
129+
});
130+
131+
// This helper overrides the send method of an EthereumProvider to allow
132+
// altering the default Hardhat node's reported results.
133+
function overrideSendOn(
134+
provider: EthereumProvider,
135+
sendOveride: (method: string, params?: any[] | undefined) => Promise<any>
136+
) {
137+
return new Proxy(provider, {
138+
get: (target: EthereumProvider, prop: keyof EthereumProvider) => {
139+
if (prop === "send") {
140+
return async (method: string, params?: any[] | undefined) => {
141+
const result = await sendOveride(method, params);
142+
143+
return result ?? target.send(method, params);
144+
};
145+
}
146+
147+
return target[prop];
148+
},
149+
});
150+
}
151+
152+
it("should default maxPriorityFeePerGas to 1 gwei (if eth_maxPriorityFeePerGas not supported)", async function () {
153+
const proxiedProvider = overrideSendOn(
154+
this.env.network.provider,
155+
async (method) => {
156+
if (method !== "eth_maxPriorityFeePerGas") {
157+
// rely on default send implementation
158+
return undefined;
159+
}
160+
161+
throw new Error("Method eth_maxPriorityFeePerGas is not supported");
162+
}
163+
);
164+
165+
const ethersProvider = new HardhatEthersProvider(
166+
proxiedProvider,
167+
this.env.network.name
168+
);
169+
170+
const feeData = await ethersProvider.getFeeData();
171+
172+
assert.equal(feeData.maxPriorityFeePerGas, 1_000_000_000n);
173+
});
174+
175+
it("should default maxPriorityFeePerGas to eth_maxPriorityFeePerGas if available", async function () {
176+
const expectedMaxPriorityFeePerGas = 4_000_000_000n;
177+
178+
const overridenEthereumProvider = overrideSendOn(
179+
this.env.network.provider,
180+
async (method) => {
181+
if (method !== "eth_maxPriorityFeePerGas") {
182+
// rely on default send implementation
183+
return undefined;
184+
}
185+
186+
return expectedMaxPriorityFeePerGas.toString();
187+
}
188+
);
189+
190+
const ethersProvider = new HardhatEthersProvider(
191+
overridenEthereumProvider,
192+
this.env.network.name
193+
);
194+
195+
const feeData = await ethersProvider.getFeeData();
196+
197+
assert.equal(feeData.maxPriorityFeePerGas, 4_000_000_000n);
198+
});
126199
});
127200

128201
describe("getBalance", function () {

0 commit comments

Comments
 (0)