Skip to content
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

Release 0.15.7 #827

Merged
merged 10 commits into from
Oct 24, 2024
5 changes: 5 additions & 0 deletions examples/complete/contracts/BasicContract.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ pragma solidity ^0.8.9;

contract BasicContract {
uint public savedArg;
address public sender;

event BasicEvent(uint eventArg);

constructor(address _sender) {
sender = _sender;
}

receive() external payable {}

function basicFunction(uint funcArg) public {
Expand Down
4 changes: 3 additions & 1 deletion examples/complete/ignition/modules/CompleteModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ const withLibArtifact = require("../../libArtifacts/ContractWithLibrary.json");
const libArtifact = require("../../libArtifacts/BasicLibrary.json");

module.exports = buildModule("CompleteModule", (m) => {
const basic = m.contract("BasicContract");
const acct2 = m.getAccount(2);

const basic = m.contract("BasicContract", [acct2]);
const library = m.library("BasicLibrary");
const libFromArtifact = m.library("BasicLibrary", libArtifact, {
id: "BasicLibrary2",
Expand Down
12 changes: 12 additions & 0 deletions packages/core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## 0.15.7 - 2024-10-24

### Added

- New CLI command `ignition transactions` to list all transactions sent for a given deployment ID, @zoeyTM ([#821](https://github.com/NomicFoundation/hardhat-ignition/pull/821))
- Module parameters can now be set at the global level using `$global`, @zoeyTM ([#819](https://github.com/NomicFoundation/hardhat-ignition/pull/819))

### Fixed

- Gas fields are now properly set for Optimistic BNB, @zoeyTM ([#826](https://github.com/NomicFoundation/hardhat-ignition/pull/826))
- Corrected resolution of artifacts when using fully qualified names in deployment modules, @kanej ([#822](https://github.com/NomicFoundation/hardhat-ignition/pull/822))

## 0.15.6 - 2024-09-25

### Added
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nomicfoundation/ignition-core",
"version": "0.15.6",
"version": "0.15.7",
"license": "MIT",
"author": "Nomic Foundation",
"homepage": "https://hardhat.org",
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ export * from "./errors";
export { IgnitionModuleSerializer } from "./ignition-module-serializer";
export { formatSolidityParameter } from "./internal/formatters";
export { listDeployments } from "./list-deployments";
export { listTransactions } from "./list-transactions";
export { status } from "./status";
export * from "./type-guards";
export * from "./types/artifact";
export * from "./types/deploy";
export * from "./types/errors";
export * from "./types/execution-events";
export * from "./types/list-transactions";
export * from "./types/module";
export * from "./types/module-builder";
export * from "./types/provider";
Expand Down
12 changes: 12 additions & 0 deletions packages/core/src/internal/errors-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ export const ERROR_RANGES: {
max: 1199,
title: "Strategy errors",
},
LIST_TRANSACTIONS: {
min: 1200,
max: 1299,
title: "List transactions errors",
},
};

/**
Expand Down Expand Up @@ -400,6 +405,13 @@ export const ERRORS = {
"Strategy configuration parameter '%paramName%' for the strategy '%strategyName%' is invalid: %reason%",
},
},
LIST_TRANSACTIONS: {
UNINITIALIZED_DEPLOYMENT: {
number: 1200,
message:
"Cannot list transactions for nonexistant deployment at %deploymentDir%",
},
},
};

/**
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/internal/execution/jsonrpc-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -654,12 +654,15 @@ export class EIP1193JsonRpcClient implements JsonRpcClient {
// 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)
// as well as opBNB (chainId 204) and its testnet (chainId 5611)
// from this logic as it is EIP-1559 compliant but
// only sets a maxPriorityFeePerGas.
if (
latestBlock.baseFeePerGas === 0n &&
chainId !== 56 &&
chainId !== 97
chainId !== 97 &&
chainId !== 204 &&
chainId !== 5611
) {
return {
maxFeePerGas: 0n,
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/internal/utils/resolve-module-parameter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export function resolveModuleParameter(
}

const moduleParameters =
context.deploymentParameters[moduleParamRuntimeValue.moduleId];
context.deploymentParameters[moduleParamRuntimeValue.moduleId] ??
context.deploymentParameters.$global;

if (moduleParameters === undefined) {
assertIgnitionInvariant(
Expand Down
176 changes: 176 additions & 0 deletions packages/core/src/list-transactions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import type { ArtifactResolver } from "./types/artifact";

import findLastIndex from "lodash/findLastIndex";

import { IgnitionError } from "./errors";
import { FileDeploymentLoader } from "./internal/deployment-loader/file-deployment-loader";
import { ERRORS } from "./internal/errors-list";
import { loadDeploymentState } from "./internal/execution/deployment-state-helpers";
import { ExecutionResultType } from "./internal/execution/types/execution-result";
import {
ExecutionSateType,
type CallExecutionState,
type DeploymentExecutionState,
type ExecutionState,
type SendDataExecutionState,
} from "./internal/execution/types/execution-state";
import {
type Transaction,
TransactionReceiptStatus,
} from "./internal/execution/types/jsonrpc";
import { JournalMessageType } from "./internal/execution/types/messages";
import { assertIgnitionInvariant } from "./internal/utils/assertions";
import {
type ListTransactionsResult,
TransactionStatus,
} from "./types/list-transactions";

/**
* Returns the transactions associated with a deployment.
*
* @param deploymentDir - the directory of the deployment to get the transactions of
* @param artifactResolver - the artifact resolver to use when loading artifacts
* for a future
*
* @beta
*/
export async function listTransactions(
deploymentDir: string,
_artifactResolver: Omit<ArtifactResolver, "getBuildInfo">
): Promise<ListTransactionsResult> {
const deploymentLoader = new FileDeploymentLoader(deploymentDir);

const deploymentState = await loadDeploymentState(deploymentLoader);

if (deploymentState === undefined) {
throw new IgnitionError(ERRORS.LIST_TRANSACTIONS.UNINITIALIZED_DEPLOYMENT, {
deploymentDir,
});
}

const transactions: ListTransactionsResult = [];

for await (const message of deploymentLoader.readFromJournal()) {
if (message.type !== JournalMessageType.TRANSACTION_SEND) {
continue;
}

const exState = deploymentState.executionStates[message.futureId];

assertIgnitionInvariant(
doesSendTransactions(exState),
"Expected execution state to be a type that sends transactions"
);

const networkInteraction =
exState.networkInteractions[message.networkInteractionId - 1];

assertIgnitionInvariant(
networkInteraction.type === "ONCHAIN_INTERACTION",
"Expected network interaction to be an onchain interaction"
);

// this seems redundant, but we use it later to determine pending vs dropped status
const lastTxIndex = findLastIndex(
networkInteraction.transactions,
(tx) => tx.hash === message.transaction.hash
);

const transaction = networkInteraction.transactions[lastTxIndex];

switch (exState.type) {
case ExecutionSateType.DEPLOYMENT_EXECUTION_STATE: {
transactions.push({
type: exState.type,
from: exState.from,
txHash: transaction.hash,
status: getTransactionStatus(
transaction,
lastTxIndex === networkInteraction.transactions.length - 1
),
name: exState.contractName,
address:
transaction.receipt?.status === TransactionReceiptStatus.SUCCESS
? exState.result?.type === ExecutionResultType.SUCCESS
? exState.result.address
: undefined
: undefined,
params: exState.constructorArgs,
value: networkInteraction.value,
});

break;
}
case ExecutionSateType.CALL_EXECUTION_STATE: {
const artifact = await deploymentLoader.loadArtifact(
exState.artifactId
);

transactions.push({
type: exState.type,
from: exState.from,
txHash: transaction.hash,
status: getTransactionStatus(
transaction,
lastTxIndex === networkInteraction.transactions.length - 1
),
name: `${artifact.contractName}#${exState.functionName}`,
to: networkInteraction.to,
params: exState.args,
value: networkInteraction.value,
});

break;
}
case ExecutionSateType.SEND_DATA_EXECUTION_STATE: {
transactions.push({
type: exState.type,
from: exState.from,
txHash: transaction.hash,
status: getTransactionStatus(
transaction,
lastTxIndex === networkInteraction.transactions.length - 1
),
to: networkInteraction.to,
value: networkInteraction.value,
});

break;
}
}
}

return transactions;
}

function doesSendTransactions(
exState: ExecutionState
): exState is
| DeploymentExecutionState
| CallExecutionState
| SendDataExecutionState {
return (
exState.type === ExecutionSateType.DEPLOYMENT_EXECUTION_STATE ||
exState.type === ExecutionSateType.CALL_EXECUTION_STATE ||
exState.type === ExecutionSateType.SEND_DATA_EXECUTION_STATE
);
}

function getTransactionStatus(
transaction: Transaction,
isFinalTransaction: boolean
): TransactionStatus {
if (transaction.receipt === undefined) {
if (isFinalTransaction) {
return TransactionStatus.PENDING;
}

return TransactionStatus.DROPPED;
}

if (transaction.receipt.status === TransactionReceiptStatus.SUCCESS) {
return TransactionStatus.SUCCESS;
}

return TransactionStatus.FAILURE;
}
37 changes: 37 additions & 0 deletions packages/core/src/types/list-transactions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { SolidityParameterType } from "./module";

/**
* The status of a transaction.
*
* @beta
*/
export enum TransactionStatus {
SUCCESS = "SUCCESS",
FAILURE = "FAILURE",
DROPPED = "DROPPED",
PENDING = "PENDING",
}

/**
* The information of a transaction.
*
* @beta
*/
export interface TransactionInfo {
type: string;
status: TransactionStatus;
txHash: string;
from: string;
to?: string;
name?: string; // can be contract name, function name, or undefined, depending on the type
address?: string;
params?: SolidityParameterType[];
value?: bigint;
}

/**
* An array of transaction information.
*
* @beta
*/
export type ListTransactionsResult = TransactionInfo[];
Loading
Loading