Skip to content

Commit

Permalink
update L2 fees logic
Browse files Browse the repository at this point in the history
  • Loading branch information
zoeyTM committed Sep 16, 2024
1 parent bf7e7fb commit adbe6ef
Show file tree
Hide file tree
Showing 28 changed files with 199 additions and 17 deletions.
14 changes: 14 additions & 0 deletions examples/fee-tester/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
extends: ["plugin:prettier/recommended"],
parserOptions: {
ecmaVersion: "latest",
},
env: {
es6: true,
node: true,
},
rules: {
"no-console": "error",
},
ignorePatterns: [".eslintrc.js", "artifacts/*", "cache/*"],
};
13 changes: 13 additions & 0 deletions examples/fee-tester/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
node_modules
.env
coverage
coverage.json
typechain
typechain-types

#Hardhat files
cache
artifacts

ignition/deployments

5 changes: 5 additions & 0 deletions examples/fee-tester/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/node_modules
/artifacts
/cache
/coverage
/.nyc_output
1 change: 1 addition & 0 deletions examples/fee-tester/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Hardhat Fee Tester for Hardhat Ignition
16 changes: 16 additions & 0 deletions examples/fee-tester/contracts/FeeTester.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;


contract FeeTester {
address public owner;

constructor() {
owner = msg.sender;
}

// arbitrary function to call during fee testing
function deleteOwner() public {
delete owner;
}
}
7 changes: 7 additions & 0 deletions examples/fee-tester/hardhat.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require("@nomicfoundation/hardhat-toolbox");
require("@nomicfoundation/hardhat-ignition-ethers");

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: "0.8.19",
};
12 changes: 12 additions & 0 deletions examples/fee-tester/ignition/modules/FeeTesterModule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// ./ignition/FeeTesterModule.js
const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules");

module.exports = buildModule("FeeTesterModule", (m) => {
const feeTester1 = m.contract("FeeTester");

m.call(feeTester1, "deleteOwner");

const feeTester2 = m.contract("FeeTester", [], { id: "feeTester2" });

return { feeTester1, feeTester2 };
});
18 changes: 18 additions & 0 deletions examples/fee-tester/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "@nomicfoundation/ignition-fee-tester-example",
"private": true,
"version": "0.15.2",
"scripts": {
"test": "hardhat test",
"lint": "npm run prettier -- --check && npm run eslint",
"lint:fix": "npm run prettier -- --write && npm run eslint -- --fix",
"eslint": "eslint \"ignition/**/*.{js,jsx}\" \"test/**/*.{js,jsx}\"",
"prettier": "prettier \"*.{js,md,json}\" \"ignition/modules/*.{js,md,json}\" \"test/*.{js,md,json}\" \"contracts/**/*.sol\""
},
"devDependencies": {
"@nomicfoundation/hardhat-ignition-ethers": "workspace:^",
"@nomicfoundation/hardhat-toolbox": "4.0.0",
"hardhat": "^2.18.0",
"prettier-plugin-solidity": "1.1.3"
}
}
6 changes: 6 additions & 0 deletions packages/core/src/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export async function deploy<
strategyConfig,
maxFeePerGasLimit,
maxPriorityFeePerGas,
gasPrice,
disableFeeBumping,
}: {
config?: Partial<DeployConfig>;
artifactResolver: ArtifactResolver;
Expand All @@ -71,6 +73,8 @@ export async function deploy<
strategyConfig?: StrategyConfig[StrategyT];
maxFeePerGasLimit?: bigint;
maxPriorityFeePerGas?: bigint;
gasPrice?: bigint;
disableFeeBumping?: boolean;
}): Promise<DeploymentResult> {
const executionStrategy: ExecutionStrategy = resolveStrategy(
strategy,
Expand Down Expand Up @@ -117,6 +121,7 @@ export async function deploy<
const jsonRpcClient = new EIP1193JsonRpcClient(provider, {
maxFeePerGasLimit,
maxPriorityFeePerGas,
gasPrice,
});

const isAutominedNetwork = await checkAutominedNetwork(provider);
Expand All @@ -126,6 +131,7 @@ export async function deploy<
requiredConfirmations: isAutominedNetwork
? DEFAULT_AUTOMINE_REQUIRED_CONFIRMATIONS
: config.requiredConfirmations ?? defaultConfig.requiredConfirmations,
disableFeeBumping: disableFeeBumping ?? defaultConfig.disableFeeBumping,
...config,
};

Expand Down
1 change: 1 addition & 0 deletions packages/core/src/internal/defaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const defaultConfig: DeployConfig = {
timeBeforeBumpingFees: 3 * 60 * 1_000,
maxFeeBumps: 4,
requiredConfirmations: 5,
disableFeeBumping: false,
};

/**
Expand Down
10 changes: 7 additions & 3 deletions packages/core/src/internal/deployer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ export class Deployer {
ignitionModule.id,
this._deploymentDir,
isResumed,
this._config.maxFeeBumps
this._config.maxFeeBumps,
this._config.disableFeeBumping
);

const contracts =
Expand Down Expand Up @@ -188,7 +189,8 @@ export class Deployer {
this._config.requiredConfirmations,
this._config.timeBeforeBumpingFees,
this._config.maxFeeBumps,
this._config.blockPollingInterval
this._config.blockPollingInterval,
this._config.disableFeeBumping
);

deploymentState = await executionEngine.executeModule(
Expand Down Expand Up @@ -270,7 +272,8 @@ export class Deployer {
moduleId: string,
deploymentDir: string | undefined,
isResumed: boolean,
maxFeeBumps: number
maxFeeBumps: number,
disableFeeBumping: boolean
): void {
if (this._executionEventListener === undefined) {
return;
Expand All @@ -282,6 +285,7 @@ export class Deployer {
deploymentDir: deploymentDir ?? undefined,
isResumed,
maxFeeBumps,
disableFeeBumping,
});
}

Expand Down
6 changes: 4 additions & 2 deletions packages/core/src/internal/execution/execution-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ export class ExecutionEngine {
private readonly _requiredConfirmations: number,
private readonly _millisecondBeforeBumpingFees: number,
private readonly _maxFeeBumps: number,
private readonly _blockPollingInterval: number
private readonly _blockPollingInterval: number,
private readonly _disableFeeBumping: boolean
) {}

/**
Expand Down Expand Up @@ -98,7 +99,8 @@ export class ExecutionEngine {
this._maxFeeBumps,
accounts,
deploymentParameters,
defaultSender
defaultSender,
this._disableFeeBumping
);

const futures = getFuturesFromModule(module);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ export class FutureProcessor {
private readonly _maxFeeBumps: number,
private readonly _accounts: string[],
private readonly _deploymentParameters: DeploymentParameters,
private readonly _defaultSender: string
private readonly _defaultSender: string,
private readonly _disableFeeBumping: boolean
) {}

/**
Expand Down Expand Up @@ -209,7 +210,9 @@ export class FutureProcessor {
this._transactionTrackingTimer,
this._requiredConfirmations,
this._millisecondBeforeBumpingFees,
this._maxFeeBumps
this._maxFeeBumps,
undefined,
this._disableFeeBumping
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ export interface GetTransactionRetryConfig {
* of a transaction.
* @param maxFeeBumps The maximum number of times we can bump the fees of a transaction
* before considering the onchain interaction timed out.
* @param getTransactionRetryConfig This is really only a parameter to help with testing this function
* @param disableFeeBumping Disables fee bumping for all transactions.
* @returns A message indicating the result of checking the transactions of the latest
* network interaction.
*/
Expand All @@ -68,7 +70,8 @@ export async function monitorOnchainInteraction(
getTransactionRetryConfig: GetTransactionRetryConfig = {
maxRetries: 10,
retryInterval: 1000,
}
},
disableFeeBumping: boolean
): Promise<
| TransactionConfirmMessage
| OnchainInteractionBumpFeesMessage
Expand Down Expand Up @@ -143,7 +146,10 @@ export async function monitorOnchainInteraction(
return undefined;
}

if (lastNetworkInteraction.transactions.length > maxFeeBumps) {
if (
disableFeeBumping ||
lastNetworkInteraction.transactions.length > maxFeeBumps
) {
return {
type: JournalMessageType.ONCHAIN_INTERACTION_TIMEOUT,
futureId: exState.id,
Expand Down
37 changes: 32 additions & 5 deletions packages/core/src/internal/execution/jsonrpc-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ export class EIP1193JsonRpcClient implements JsonRpcClient {
private readonly _config?: {
maxFeePerGasLimit?: bigint;
maxPriorityFeePerGas?: bigint;
gasPrice?: bigint;
}
) {}

Expand Down Expand Up @@ -643,9 +644,13 @@ 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) {
// polygon (chainId 137) and polygon's amoy testnet (chainId 80002)
// both require legacy gasPrice fees so we skip EIP-1559 logic in those cases
if (
latestBlock.baseFeePerGas !== undefined &&
chainId !== 137 &&
chainId !== 80002
) {
// Support zero gas fee chains, such as a private instances
// of blockchains using Besu. We explicitly exclude BNB
// Smartchain (chainId 56) and its testnet (chainId 97)
Expand Down Expand Up @@ -674,6 +679,28 @@ export class EIP1193JsonRpcClient implements JsonRpcClient {
};
}

/**
* Polygon amoy testnet (chainId 80002) currently has a bug causing the
* `eth_gasPrice` RPC call to return an amount that is way too high.
* We hardcode the gas price for this chain for now until the bug is fixed.
* See: https://github.com/maticnetwork/bor/issues/1213
*
* Note that at the time of this implementation, the issue was autoclosed by a bot
* as a maintainer had not responded to the issue yet. Users continue to report
* the bug in the issue comments, however.
*
* All of that to say, when evaluating whether this logic is still needed in the future,
* it will likely be required to read through the issue above, rather than relying on the
* status of the github issue itself.
*/
if (chainId === 80002) {
return { gasPrice: 32000000000n };
}

if (this._config?.gasPrice !== undefined) {
return { gasPrice: this._config.gasPrice };
}

const response = await this._provider.request({
method: "eth_gasPrice",
params: [],
Expand All @@ -699,7 +726,7 @@ export class EIP1193JsonRpcClient implements JsonRpcClient {
}

try {
return await this._getMaxPrioirtyFeePerGas();
return await this._getMaxPriorityFeePerGas();
} catch {
// the max priority fee RPC call is not supported by
// this chain
Expand All @@ -708,7 +735,7 @@ export class EIP1193JsonRpcClient implements JsonRpcClient {
return DEFAULT_MAX_PRIORITY_FEE_PER_GAS;
}

private async _getMaxPrioirtyFeePerGas(): Promise<bigint> {
private async _getMaxPriorityFeePerGas(): Promise<bigint> {
const fee = await this._provider.request({
method: "eth_maxPriorityFeePerGas",
});
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/types/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ export interface DeployConfig {
* a transaction to be confirmed during Ignition execution.
*/
requiredConfirmations: number;

/**
* Disables fee bumping for all transactions.
*/
disableFeeBumping: boolean;
}

/**
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/types/execution-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export interface DeploymentStartEvent {
deploymentDir: string | undefined;
isResumed: boolean;
maxFeeBumps: number;
disableFeeBumping: boolean;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,8 @@ describe("Network interactions", () => {
requiredConfirmations,
millisecondBeforeBumpingFees,
maxFeeBumps,
testGetTransactionRetryConfig
testGetTransactionRetryConfig,
false
);

if (message === undefined) {
Expand Down Expand Up @@ -286,7 +287,8 @@ describe("Network interactions", () => {
requiredConfirmations,
millisecondBeforeBumpingFees,
maxFeeBumps,
testGetTransactionRetryConfig
testGetTransactionRetryConfig,
false
),
/IGN401: Error while executing test: all the transactions of its network interaction 1 were dropped\. Please try rerunning Hardhat Ignition\./
);
Expand Down
3 changes: 2 additions & 1 deletion packages/core/test/execution/future-processor/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ export async function setupFutureProcessor(
100, // maxFeeBumps
exampleAccounts,
{},
getDefaultSender(exampleAccounts)
getDefaultSender(exampleAccounts),
false // disableFeeBumping
);

return { processor, storedDeployedAddresses };
Expand Down
5 changes: 5 additions & 0 deletions packages/hardhat-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ extendConfig((config, userConfig) => {
config.networks[networkName].ignition = {
maxFeePerGasLimit: userNetworkConfig.ignition?.maxFeePerGasLimit,
maxPriorityFeePerGas: userNetworkConfig.ignition?.maxPriorityFeePerGas,
gasPrice: userNetworkConfig.ignition?.gasPrice,
disableFeeBumping: userNetworkConfig.ignition?.disableFeeBumping,
};
});

Expand Down Expand Up @@ -320,6 +322,9 @@ ignitionScope
maxPriorityFeePerGas:
hre.config.networks[hre.network.name]?.ignition
.maxPriorityFeePerGas,
gasPrice: hre.config.networks[hre.network.name]?.ignition.gasPrice,
disableFeeBumping:
hre.config.networks[hre.network.name]?.ignition.disableFeeBumping,
});

try {
Expand Down
Loading

0 comments on commit adbe6ef

Please sign in to comment.