Skip to content

Commit

Permalink
Squash all of the stack trace port commits
Browse files Browse the repository at this point in the history
  • Loading branch information
fvictorio authored and Xanewok committed Aug 21, 2024
1 parent f944cd5 commit 72cd342
Show file tree
Hide file tree
Showing 21 changed files with 256 additions and 5,348 deletions.
147 changes: 75 additions & 72 deletions docs/src/content/ignition/docs/advanced/migrating.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,77 +8,77 @@ To get started, we’ll uninstall the `hardhat-deploy` plugin and install the Ha

1. Remove the `hardhat-deploy` packages from your project:

::::tabsgroup{options="npm,yarn"}
::::tabsgroup{options="npm,yarn"}

:::tab{value="npm"}
:::tab{value="npm"}

```sh
npm uninstall hardhat-deploy hardhat-deploy-ethers
```
```sh
npm uninstall hardhat-deploy hardhat-deploy-ethers
```

:::
:::

:::tab{value=yarn}
:::tab{value=yarn}

```sh
yarn remove hardhat-deploy hardhat-deploy-ethers
```
```sh
yarn remove hardhat-deploy hardhat-deploy-ethers
```

:::
:::

::::
::::

2. Install the Hardhat Ignition package and `hardhat-network-helpers` to provide additional testing support as a replacement for `hardhat-deploy` functionality like EVM snapshots:

::::tabsgroup{options="npm,yarn"}
::::tabsgroup{options="npm,yarn"}

:::tab{value="npm"}
:::tab{value="npm"}

```sh
npm install --save-dev @nomicfoundation/hardhat-ignition-ethers @nomicfoundation/hardhat-network-helpers
```
```sh
npm install --save-dev @nomicfoundation/hardhat-ignition-ethers @nomicfoundation/hardhat-network-helpers
```

:::
:::

:::tab{value=yarn}
:::tab{value=yarn}

```sh
yarn add --dev @nomicfoundation/hardhat-ignition-ethers @nomicfoundation/hardhat-network-helpers
```
```sh
yarn add --dev @nomicfoundation/hardhat-ignition-ethers @nomicfoundation/hardhat-network-helpers
```

:::
:::

::::
::::

3. Update the project’s `hardhat.config` file to remove `hardhat-deploy` and `hardhat-deploy-ethers` and instead import Hardhat Ignition:

::::tabsgroup{options="typescript,javascript"}
::::tabsgroup{options="typescript,javascript"}

:::tab{value="typescript"}
:::tab{value="typescript"}

```git
- import "hardhat-deploy";
- import "hardhat-deploy-ethers";
+ import "@nomicfoundation/hardhat-ignition-ethers";
```
```git
- import "hardhat-deploy";
- import "hardhat-deploy-ethers";
+ import "@nomicfoundation/hardhat-ignition-ethers";
```

:::
:::

:::tab{value=javascript}
:::tab{value=javascript}

```git
- require("hardhat-deploy");
- require("hardhat-deploy-ethers");
+ require("@nomicfoundation/hardhat-ignition-ethers");
```
```git
- require("hardhat-deploy");
- require("hardhat-deploy-ethers");
+ require("@nomicfoundation/hardhat-ignition-ethers");
```

:::
:::

::::
::::

## Convert deployment scripts to Ignition Modules

`hardhat-deploy` represents contract deployments as JavaScript or TypeScript files under the `./deploy/` folder. Hardhat Ignition follows a similar pattern with deployments encapsulated as modules; these are JS/TS files stored under the `./ignition/modules directory`. Each `hardhat-deploy` deploy file will be converted or merged into a Hardhat Ignition module.
`hardhat-deploy` represents contract deployments as JavaScript or TypeScript files under the `./deploy/` folder. Hardhat Ignition follows a similar pattern with deployments encapsulated as modules; these are JS/TS files stored under the `./ignition/modules` directory. Each `hardhat-deploy` deploy file will be converted or merged into a Hardhat Ignition module.

Let’s first create the required folder structure under the root of your project:

Expand All @@ -97,13 +97,16 @@ contract Token {
uint256 public totalSupply = 1000000;
address public owner;
mapping(address => uint256) balances;
constructor(address _owner) {
balances[_owner] = totalSupply;
owner = _owner;
}
function balanceOf(address account) external view returns (uint256) {
return balances[account];
}
function transfer(address to, uint256 amount) external {
require(balances[msg.sender] >= amount, "Not enough tokens");
balances[msg.sender] -= amount;
Expand All @@ -123,9 +126,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const { deployments, getNamedAccounts } = hre;
const { deploy } = deployments;
/*
The deploy function uses the hardhat-deploy named accounts feature
to set the deployment's `from` and `args` parameters.
*/
The deploy function uses the hardhat-deploy named accounts feature
to set the deployment's `from` and `args` parameters.
*/
const { deployer, tokenOwner } = await getNamedAccounts();
await deploy("Token", {
from: deployer,
Expand All @@ -152,29 +155,29 @@ import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
For instance, you can deploy contracts via `m.contract()`.
*/
export default buildModule("TokenModule", (m) => {
/*
Instead of named accounts, you get access to the configured accounts
through the `getAccount()` method.
*/
/*
Instead of named accounts, you get access to the configured accounts
through the `getAccount()` method.
*/
const deployer = m.getAccount(0);
const tokenOwner = m.getAccount(1);
/*
Deploy `Token` by calling `contract()` with the constructor arguments
as the second argument. The account to use for the deployment transaction
is set through `from` in the third argument, which is an options object.
*/
Deploy `Token` by calling `contract()` with the constructor arguments
as the second argument. The account to use for the deployment transaction
is set through `from` in the third argument, which is an options object.
*/
const token = m.contract("Token", [tokenOwner], {
from: deployer,
});
/*
The call to `m.contract()` returns a future that can be used in other `m.contract()`
calls (e.g. as a constructor argument, where the future will resolve to the
deployed address), but it can also be returned from the module. Contract
futures that are returned from the module can be leveraged in Hardhat tests
and scripts, as will be shown later.
*/
The call to `m.contract()` returns a future that can be used in other `m.contract()`
calls (e.g. as a constructor argument, where the future will resolve to the
deployed address), but it can also be returned from the module. Contract
futures that are returned from the module can be leveraged in Hardhat tests
and scripts, as will be shown later.
*/
return { token };
});
```
Expand All @@ -193,29 +196,29 @@ const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules");
For instance, you can deploy contracts via `m.contract()`.
*/
module.exports = buildModule("TokenModule", (m) => {
/*
Instead of named accounts, you get access to the configured accounts
through the `getAccount()` method.
*/
/*
Instead of named accounts, you get access to the configured accounts
through the `getAccount()` method.
*/
const deployer = m.getAccount(0);
const tokenOwner = m.getAccount(1);
/*
Deploy `Token` by calling `contract()` with the constructor arguments
as the second argument. The account to use for the deployment transaction
is set through `from` in the third argument, which is an options object.
*/
Deploy `Token` by calling `contract()` with the constructor arguments
as the second argument. The account to use for the deployment transaction
is set through `from` in the third argument, which is an options object.
*/
const token = m.contract("Token", [tokenOwner], {
from: deployer,
});
/*
The call to `m.contract()` returns a future that can be used in other `m.contract()`
calls (e.g. as a constructor argument, where the future will resolve to the
deployed address), but it can also be returned from the module. Contract
futures that are returned from the module can be leveraged in Hardhat tests
and scripts, as will be shown later.
*/
The call to `m.contract()` returns a future that can be used in other `m.contract()`
calls (e.g. as a constructor argument, where the future will resolve to the
deployed address), but it can also be returned from the module. Contract
futures that are returned from the module can be leveraged in Hardhat tests
and scripts, as will be shown later.
*/
return { token };
});
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import type {
import type {
EdrContext,
Provider as EdrProviderT,
VmTraceDecoder as VmTraceDecoderT,
VMTracer as VMTracerT,
RawTrace,
Response,
SubscriptionEvent,
Expand Down Expand Up @@ -43,7 +45,6 @@ import { isErrorResponse } from "../../core/providers/http";
import { getHardforkName } from "../../util/hardforks";
import { createModelsAndDecodeBytecodes } from "../stack-traces/compiler-to-model";
import { ConsoleLogger } from "../stack-traces/consoleLogger";
import { ContractsIdentifier } from "../stack-traces/contracts-identifier";
import {
VmTraceDecoder,
initializeVmTraceDecoder,
Expand Down Expand Up @@ -169,15 +170,15 @@ export class EdrProviderWrapper
private _callOverrideCallback?: CallOverrideCallback;

/** Used for internal stack trace tests. */
private _vmTracer?: VMTracer;
private _vmTracer?: VMTracerT;

private constructor(
private readonly _provider: EdrProviderT,
// we add this for backwards-compatibility with plugins like solidity-coverage
private readonly _node: {
_vm: MinimalEthereumJsVm;
},
private readonly _vmTraceDecoder: VmTraceDecoder,
private readonly _vmTraceDecoder: VmTraceDecoderT,
// The common configuration for EthereumJS VM is not used by EDR, but tests expect it as part of the provider.
private readonly _common: Common,
tracingConfig?: TracingConfig
Expand Down Expand Up @@ -223,8 +224,7 @@ export class EdrProviderWrapper
const printLineFn = loggerConfig.printLineFn ?? printLine;
const replaceLastLineFn = loggerConfig.replaceLastLineFn ?? replaceLastLine;

const contractsIdentifier = new ContractsIdentifier();
const vmTraceDecoder = new VmTraceDecoder(contractsIdentifier);
const vmTraceDecoder = new VmTraceDecoder();

const hardforkName = getHardforkName(config.hardfork);

Expand Down Expand Up @@ -364,6 +364,9 @@ export class EdrProviderWrapper
if (needsTraces) {
const rawTraces = responseObject.traces;
for (const rawTrace of rawTraces) {
this._vmTracer?.observe(rawTrace);

// For other consumers in JS we need to marshall the entire trace over FFI
const trace = rawTrace.trace();

// beforeTx event
Expand All @@ -380,8 +383,6 @@ export class EdrProviderWrapper
edrTracingStepToMinimalInterpreterStep(traceItem)
);
}

this._vmTracer?.addStep(traceItem);
}
// afterMessage event
else if ("executionResult" in traceItem) {
Expand All @@ -391,8 +392,6 @@ export class EdrProviderWrapper
edrTracingMessageResultToMinimalEVMResult(traceItem)
);
}

this._vmTracer?.addAfterMessage(traceItem.executionResult);
}
// beforeMessage event
else {
Expand All @@ -402,8 +401,6 @@ export class EdrProviderWrapper
edrTracingMessageToMinimalMessage(traceItem)
);
}

this._vmTracer?.addBeforeMessage(traceItem);
}
}

Expand Down Expand Up @@ -470,7 +467,7 @@ export class EdrProviderWrapper
*
* Used for internal stack traces integration tests.
*/
public setVmTracer(vmTracer?: VMTracer) {
public setVmTracer(vmTracer?: VMTracerT) {
this._vmTracer = vmTracer;
}

Expand Down Expand Up @@ -548,7 +545,7 @@ export class EdrProviderWrapper
);

log(
"ContractsIdentifier failed to be updated. Please report this to help us improve Hardhat.\n",
"VmTraceDecoder failed to be updated. Please report this to help us improve Hardhat.\n",
error
);

Expand All @@ -574,17 +571,7 @@ export class EdrProviderWrapper
rawTrace: RawTrace
): Promise<SolidityStackTrace | undefined> {
const vmTracer = new VMTracer();

const trace = rawTrace.trace();
for (const traceItem of trace) {
if ("pc" in traceItem) {
vmTracer.addStep(traceItem);
} else if ("executionResult" in traceItem) {
vmTracer.addAfterMessage(traceItem.executionResult);
} else {
vmTracer.addBeforeMessage(traceItem);
}
}
vmTracer.observe(rawTrace);

let vmTrace = vmTracer.getLastTopLevelMessageTrace();
const vmTracerError = vmTracer.getLastError();
Expand Down
Loading

0 comments on commit 72cd342

Please sign in to comment.