diff --git a/packages/core/src/internal/execution/jsonrpc-client.ts b/packages/core/src/internal/execution/jsonrpc-client.ts index b45c1cef9..59d336d59 100644 --- a/packages/core/src/internal/execution/jsonrpc-client.ts +++ b/packages/core/src/internal/execution/jsonrpc-client.ts @@ -12,6 +12,8 @@ import { } from "./types/jsonrpc"; import { toChecksumFormat } from "./utils/address"; +const DEFAULT_MAX_FEE_PER_GAS = 1_000_000_000n; + /** * The params to make an `eth_call`. */ @@ -638,9 +640,9 @@ export class EIP1193JsonRpcClient implements JsonRpcClient { // We prioritize EIP-1559 fees over legacy gasPrice fees, however, // polygon (chainId 137) requires legacy gasPrice fees so we skip EIP-1559 logic in that case if (latestBlock.baseFeePerGas !== undefined && chainId !== 137) { + const maxPriorityFeePerGas = await this._resolveMaxFeePerGas(); + // Logic copied from ethers v6 - const maxPriorityFeePerGas = - this._config?.maxPriorityFeePerGas ?? 1_000_000_000n; // 1gwei const maxFeePerGas = latestBlock.baseFeePerGas * 2n + maxPriorityFeePerGas; @@ -659,6 +661,44 @@ export class EIP1193JsonRpcClient implements JsonRpcClient { return { gasPrice: jsonRpcQuantityToBigInt(response) }; } + + /** + * The max fee per gas is needed in the max fee calculation. + * + * It is resolved from config if present, falling back to + * the `eth_maxPriorityFeePerGas` RPC call if supported by the chain, + * and finally falling back to the default max fee per gas. + * + * @returns a max fee per gas based on the config, RPC call, or default value. + */ + private async _resolveMaxFeePerGas(): Promise { + if (this._config?.maxPriorityFeePerGas !== undefined) { + return this._config?.maxPriorityFeePerGas; + } + + try { + return await this._getMaxPrioirtyFeePerGas(); + } catch { + // the max priority fee RPC call is not supported by + // this chain + } + + return DEFAULT_MAX_FEE_PER_GAS; + } + + private async _getMaxPrioirtyFeePerGas(): Promise { + const fee = await this._provider.request({ + method: "eth_maxPriorityFeePerGas", + }); + + assertResponseType( + "eth_maxPriorityFeePerGas", + fee, + typeof fee === "string" + ); + + return jsonRpcQuantityToBigInt(fee); + } } /** diff --git a/packages/core/test-integrations/new-api/internal/new-execution/jsonrpc-client.ts b/packages/core/test-integrations/new-api/internal/new-execution/jsonrpc-client.ts index 48bd95e73..c27bfdc56 100644 --- a/packages/core/test-integrations/new-api/internal/new-execution/jsonrpc-client.ts +++ b/packages/core/test-integrations/new-api/internal/new-execution/jsonrpc-client.ts @@ -153,6 +153,56 @@ describe("JSON-RPC client", function () { assert.equal(fees.gasPrice, 1n); }); + + it("Should use the `maxPriorityFeePerGas` from the node if `eth_maxPriorityFeePerGas` is present (and there is no config)", async function () { + // TODO: Hardhat does not support `eth_maxPriorityFeePerGas` yet, when it does, this + // can be removed. + const proxiedProvider = { + ...this.hre.network.provider, + request: async (req: { method: string }) => { + if (req.method === "eth_maxPriorityFeePerGas") { + return "2000000000"; + } + + return this.hre.network.provider.request(req); + }, + }; + + const maxFeeClient = new EIP1193JsonRpcClient(proxiedProvider, { + maxPriorityFeePerGas: undefined, // no config set for maxPriorityFeePerGas + }); + + const fees = await maxFeeClient.getNetworkFees(); + + assert("maxPriorityFeePerGas" in fees); + + assert.equal(fees.maxPriorityFeePerGas, 2_000_000_000n); + }); + + it("Should default to 1gwei for maxPriorityFeePerGas if `eth_maxPriorityFeePerGas` is not available and no config set", async function () { + const proxiedProvider = { + ...this.hre.network.provider, + request: async (req: { method: string }) => { + if (req.method === "eth_maxPriorityFeePerGas") { + throw new Error( + "Method eth_maxPriorityFeePerGas is not supported" + ); + } + + return this.hre.network.provider.request(req); + }, + }; + + const maxFeeClient = new EIP1193JsonRpcClient(proxiedProvider, { + maxPriorityFeePerGas: undefined, // no config set for maxPriorityFeePerGas + }); + + const fees = await maxFeeClient.getNetworkFees(); + + assert("maxPriorityFeePerGas" in fees); + + assert.equal(fees.maxPriorityFeePerGas, 1_000_000_000n); + }); }); });