Skip to content

Commit

Permalink
feat: add max priority fee per gas from RPC
Browse files Browse the repository at this point in the history
Before falling back to the default max priority fee (currently 1gwei) attempt
to call `eth_maxPriorityFeePerGas` as an RPC call and use that if available.

If the user has set a `maxPriorityFeePerGas` in config, that takes priority over
the RPC call.

Resolves #743
  • Loading branch information
kanej committed Apr 30, 2024
1 parent 592f9d2 commit d21796a
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 2 deletions.
44 changes: 42 additions & 2 deletions packages/core/src/internal/execution/jsonrpc-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
*/
Expand Down Expand Up @@ -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;

Expand All @@ -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<bigint> {
if (this._config?.maxPriorityFeePerGas !== undefined) {
return this._config?.maxPriorityFeePerGas;
}

try {
return await this._getMaxPrioirtyFeePerGas();
} catch {
// the max prioirty fee RPC call is not supported by
// this chain
}

return DEFAULT_MAX_FEE_PER_GAS;
}

private async _getMaxPrioirtyFeePerGas(): Promise<bigint> {
const fee = await this._provider.request({
method: "eth_maxPriorityFeePerGas",
});

assertResponseType(
"eth_maxPriorityFeePerGas",
fee,
typeof fee === "string"
);

return jsonRpcQuantityToBigInt(fee);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
});

Expand Down

0 comments on commit d21796a

Please sign in to comment.