Skip to content

Port transaction hash bug to v3 #6429

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/giant-ants-protect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@nomicfoundation/ignition-core": patch
"@nomicfoundation/ignition-ui": patch
"@nomicfoundation/hardhat-ignition": patch
"hardhat": patch
---

Port transaction hash bug fix to v3 ([#6429](https://github.com/NomicFoundation/hardhat/pull/6429))
55 changes: 55 additions & 0 deletions v-next/hardhat-errors/src/descriptors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ export const ERROR_CATEGORIES: {
max: 11299,
websiteSubTitle: "List transactions errors",
},
TRACK_TRANSACTIONS: {
min: 11300,
max: 11399,
websiteSubTitle: "Track transactions errors",
},
},
},
HARDHAT_ETHERS: {
Expand Down Expand Up @@ -1506,6 +1511,14 @@ Please review the error message and try again.`,
websiteTitle: "Gas estimation failed",
websiteDescription: `Gas estimation failed`,
},
TRANSACTION_LOST: {
number: 10410,
messageTemplate: `An error occured while trying to send a transaction for future {futureId}.
Please use a block explorer to find the hash of the transaction with nonce {nonce} sent from account {sender} and use the following command to add it to your deployment:
npx hardhat ignition track-tx <txHash> <deploymentId> --network <networkName>`,
websiteTitle: "Transaction lost",
websiteDescription: `An error occured while trying to send a transaction`,
},
},
RECONCILIATION: {
INVALID_EXECUTION_STATUS: {
Expand Down Expand Up @@ -1809,6 +1822,48 @@ Please review the error message and try again.`,
websiteDescription: `Cannot list transactions for nonexistant deployment`,
},
},
TRACK_TRANSACTIONS: {
DEPLOYMENT_DIR_NOT_FOUND: {
number: 11300,
messageTemplate: "Deployment directory {deploymentDir} not found",
websiteTitle: "Deployment directory not found",
websiteDescription: `The deployment directory was not found`,
},
UNINITIALIZED_DEPLOYMENT: {
number: 11301,
messageTemplate:
"Cannot track transaction for nonexistant deployment at {deploymentDir}",
websiteTitle: "Uninitialized deployment",
websiteDescription: `Cannot track transaction for nonexistant deployment`,
},
TRANSACTION_NOT_FOUND: {
number: 11302,
messageTemplate: `Transaction {txHash} not found. Please double check the transaction hash and try again.`,
websiteTitle: "Transaction not found",
websiteDescription: `The transaction hash you provided was not found on the network.`,
},
MATCHING_NONCE_NOT_FOUND: {
number: 11303,
messageTemplate: `The transaction you provided doesn't seem to belong to your deployment.
Please double check the error you are getting when running Hardhat Ignition, and the instructions it's providing.`,
websiteTitle: "Matching nonce not found",
websiteDescription: `The transaction you provided doesn't seem to belong to your deployment.`,
},
KNOWN_TRANSACTION: {
number: 11304,
messageTemplate: `The transaction hash that you provided was already present in your deployment.
Please double check the error you are getting when running Hardhat Ignition, and the instructions it's providing.`,
websiteTitle: "Known transaction",
websiteDescription: `The transaction hash that you provided was already present in your deployment.`,
},
INSUFFICIENT_CONFIRMATIONS: {
number: 11305,
messageTemplate: `The transaction you provided doesn't have enough confirmations yet.
Please try again later.`,
websiteTitle: "Insufficient confirmations",
websiteDescription: `The transaction you provided doesn't have enough confirmations yet.`,
},
},
},
HARDHAT_ETHERS: {
GENERAL: {
Expand Down
1 change: 1 addition & 0 deletions v-next/hardhat-ignition-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ export * from "./types/provider.js";
export * from "./types/serialization.js";
export * from "./types/status.js";
export * from "./types/verify.js";
export { trackTransaction } from "./track-transaction.js";
export { getVerificationInformation } from "./verify.js";
export { wipe } from "./wipe.js";
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ export async function initializeDeploymentState(
* This function applies a new message to the deployment state, recording it to the
* journal if needed.
*
* @param message The message to apply.
* @param deploymentState The original deployment state.
* @param deploymentLoader The deployment loader that will be used to record the message.
* @param message - The message to apply.
* @param deploymentState - The original deployment state.
* @param deploymentLoader - The deployment loader that will be used to record the message.
* @returns The new deployment state.
*/
export async function applyNewMessage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ import type {
} from "../../types/module.js";
import type { DeploymentLoader } from "../deployment-loader/types.js";

import { HardhatError } from "@nomicfoundation/hardhat-errors";
import sortBy from "lodash-es/sortBy.js";

import { ExecutionEventType } from "../../types/execution-events.js";
import { assertIgnitionInvariant } from "../utils/assertions.js";
import { getFuturesFromModule } from "../utils/get-futures-from-module.js";
import { getNetworkExecutionStates } from "../views/execution-state/get-network-execution-states.js";
import { getPendingNonceAndSender } from "../views/execution-state/get-pending-nonce-and-sender.js";
import { hasExecutionSucceeded } from "../views/has-execution-succeeded.js";
import { isBatchFinished } from "../views/is-batch-finished.js";
Expand All @@ -26,6 +28,7 @@ import { getMaxNonceUsedBySender } from "./nonce-management/get-max-nonce-used-b
import { getNonceSyncMessages } from "./nonce-management/get-nonce-sync-messages.js";
import { JsonRpcNonceManager } from "./nonce-management/json-rpc-nonce-manager.js";
import { TransactionTrackingTimer } from "./transaction-tracking-timer.js";
import { NetworkInteractionType } from "./types/network-interaction.js";

/**
* This class is used to execute a module to completion, returning the new
Expand Down Expand Up @@ -69,6 +72,8 @@ export class ExecutionEngine {
deploymentParameters: DeploymentParameters,
defaultSender: string,
): Promise<DeploymentState> {
await this._checkForMissingTransactions(deploymentState);

deploymentState = await this._syncNonces(
deploymentState,
module,
Expand Down Expand Up @@ -199,6 +204,35 @@ export class ExecutionEngine {
}
}

/**
* Checks the journal for missing transactions, throws if any are found
* and asks the user to track the missing transaction via the `track-tx` command.
*/
private async _checkForMissingTransactions(
deploymentState: DeploymentState,
): Promise<void> {
const exStates = getNetworkExecutionStates(deploymentState);

for (const exState of exStates) {
for (const ni of exState.networkInteractions) {
if (
ni.type === NetworkInteractionType.ONCHAIN_INTERACTION &&
ni.nonce !== undefined &&
ni.transactions.length === 0
) {
throw new HardhatError(
HardhatError.ERRORS.IGNITION.EXECUTION.TRANSACTION_LOST,
{
futureId: exState.id,
nonce: ni.nonce,
sender: exState.from,
},
);
}
}
}
}

/**
* Syncs the nonces of the deployment state with the blockchain, returning
* the new deployment state, and throwing if they can't be synced.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ export class FutureProcessor {
this._jsonRpcClient,
this._nonceManager,
this._transactionTrackingTimer,
this._deploymentLoader,
);

case NextAction.QUERY_STATIC_CALL:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type {
TransactionSendMessage,
} from "../../types/messages.js";

import { DeploymentLoader } from "../../../deployment-loader/types.js";
import { assertIgnitionInvariant } from "../../../utils/assertions.js";
import { ExecutionResultType } from "../../types/execution-result.js";
import { JournalMessageType } from "../../types/messages.js";
Expand Down Expand Up @@ -58,6 +59,7 @@ export async function sendTransaction(
jsonRpcClient: JsonRpcClient,
nonceManager: NonceManager,
transactionTrackingTimer: TransactionTrackingTimer,
deploymentLoader: DeploymentLoader,
): Promise<
| TransactionSendMessage
| DeploymentExecutionStateCompleteMessage
Expand Down Expand Up @@ -89,6 +91,8 @@ export async function sendTransaction(
lastNetworkInteraction,
nonceManager,
decodeSimulationResult(strategyGenerator, exState),
deploymentLoader,
exState.id,
);

// If the transaction failed during simulation, we need to revert the nonce allocation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ import type {

import { HardhatError } from "@nomicfoundation/hardhat-errors";

import { DeploymentLoader } from "../../../deployment-loader/types.js";
import { assertIgnitionInvariant } from "../../../utils/assertions.js";
import { JournalMessageType } from "../../types/messages.js";

/**
* Runs a StaticCall NetworkInteraction to completion, returning its raw result.
Expand Down Expand Up @@ -108,12 +110,14 @@ export async function sendTransactionForOnchainInteraction(
| StrategySimulationErrorExecutionResult
| undefined
>,
deploymentLoader: DeploymentLoader,
futureId: string,
): Promise<
| SimulationErrorExecutionResult
| StrategySimulationErrorExecutionResult
| {
type: typeof TRANSACTION_SENT_TYPE;
transaction: Transaction;
transaction: Pick<Transaction, "hash" | "fees">;
nonce: number;
}
> {
Expand Down Expand Up @@ -207,6 +211,13 @@ export async function sendTransactionForOnchainInteraction(
return decodedSimulationResult;
}

await deploymentLoader.recordToJournal({
type: JournalMessageType.TRANSACTION_PREPARE_SEND,
futureId,
networkInteractionId: onchainInteraction.id,
nonce: transactionParams.nonce,
});

const txHash = await client.sendTransaction(transactionParams);

return {
Expand Down
Loading
Loading