Skip to content

Commit

Permalink
Add support for ethers v6
Browse files Browse the repository at this point in the history
  • Loading branch information
fvictorio committed May 12, 2023
1 parent 4106862 commit a5b0033
Show file tree
Hide file tree
Showing 59 changed files with 4,310 additions and 1,605 deletions.
2 changes: 1 addition & 1 deletion config/eslint/eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ module.exports = {
"no-cond-assign": "error",
"no-debugger": "error",
"no-duplicate-case": "error",
"no-duplicate-imports": "error",
"@typescript-eslint/no-duplicate-imports": "error",
"no-eval": "error",
"no-extra-bind": "error",
"no-new-func": "error",
Expand Down
3 changes: 3 additions & 0 deletions packages/hardhat-chai-matchers/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ module.exports = {
project: `${__dirname}/src/tsconfig.json`,
sourceType: "module",
},
rules: {
"@typescript-eslint/no-non-null-assertion": "error"
}
};
12 changes: 6 additions & 6 deletions packages/hardhat-chai-matchers/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nomicfoundation/hardhat-chai-matchers",
"version": "1.0.6",
"version": "2.0.0",
"description": "Hardhat utils for testing",
"homepage": "https://github.com/nomicfoundation/hardhat/tree/main/packages/hardhat-chai-matchers",
"repository": "github:nomicfoundation/hardhat",
Expand All @@ -19,7 +19,7 @@
"lint:fix": "yarn prettier --write && yarn eslint --fix",
"eslint": "eslint 'src/**/*.ts' 'test/**/*.ts'",
"prettier": "prettier \"**/*.{js,md,json}\"",
"test": "mocha --recursive \"test/**/*.ts\" --exit --reporter dot",
"test": "mocha --recursive \"test/**/*.ts\" --exit",
"test:ci": "yarn test && node scripts/check-subpath-exports.js",
"build": "tsc --build .",
"prepublishOnly": "yarn build",
Expand All @@ -37,7 +37,7 @@
"README.md"
],
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.0",
"@nomiclabs/hardhat-ethers": "^3.0.0",
"@types/bn.js": "^5.1.0",
"@types/chai": "^4.2.0",
"@types/mocha": ">=9.1.0",
Expand All @@ -52,7 +52,7 @@
"eslint-plugin-import": "2.24.1",
"eslint-plugin-no-only-tests": "3.0.0",
"eslint-plugin-prettier": "3.4.0",
"ethers": "^5.0.0",
"ethers": "^6.1.0",
"get-port": "^5.1.1",
"hardhat": "^2.9.4",
"mocha": "^10.0.0",
Expand All @@ -62,9 +62,9 @@
"typescript": "~4.7.4"
},
"peerDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.0",
"@nomiclabs/hardhat-ethers": "^3.0.0",
"chai": "^4.2.0",
"ethers": "^5.0.0",
"ethers": "^6.1.0",
"hardhat": "^2.9.4"
},
"dependencies": {
Expand Down
52 changes: 30 additions & 22 deletions packages/hardhat-chai-matchers/src/internal/changeEtherBalance.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,40 @@
import type { BigNumberish, providers } from "ethers";
import type {
Addressable,
BigNumberish,
TransactionResponse,
default as EthersT,
} from "ethers";

import { buildAssert } from "../utils";
import { ensure } from "./calledOnContract/utils";
import { Account, getAddressOf } from "./misc/account";
import { getAddressOf } from "./misc/account";
import { BalanceChangeOptions } from "./misc/balance";
import { assertIsNotNull } from "./utils";

export function supportChangeEtherBalance(Assertion: Chai.AssertionStatic) {
Assertion.addMethod(
"changeEtherBalance",
function (
this: any,
account: Account | string,
account: Addressable | string,
balanceChange: BigNumberish,
options?: BalanceChangeOptions
) {
const { BigNumber } = require("ethers");

const { toBigInt } = require("ethers") as typeof EthersT;
// capture negated flag before async code executes; see buildAssert's jsdoc
const negated = this.__flags.negate;
const subject = this._obj;

const checkBalanceChange = ([actualChange, address]: [
typeof BigNumber,
bigint,
string
]) => {
const assert = buildAssert(negated, checkBalanceChange);

const expectedChange = toBigInt(balanceChange);

assert(
actualChange.eq(BigNumber.from(balanceChange)),
actualChange === expectedChange,
`Expected the ether balance of "${address}" to change by ${balanceChange.toString()} wei, but it changed by ${actualChange.toString()} wei`,
`Expected the ether balance of "${address}" NOT to change by ${balanceChange.toString()} wei, but it did`
);
Expand All @@ -47,19 +54,16 @@ export function supportChangeEtherBalance(Assertion: Chai.AssertionStatic) {

export async function getBalanceChange(
transaction:
| providers.TransactionResponse
| Promise<providers.TransactionResponse>
| (() =>
| Promise<providers.TransactionResponse>
| providers.TransactionResponse),
account: Account | string,
| TransactionResponse
| Promise<TransactionResponse>
| (() => Promise<TransactionResponse> | TransactionResponse),
account: Addressable | string,
options?: BalanceChangeOptions
) {
const { BigNumber } = await import("ethers");
): Promise<bigint> {
const hre = await import("hardhat");
const provider = hre.network.provider;

let txResponse: providers.TransactionResponse;
let txResponse: TransactionResponse;

if (typeof transaction === "function") {
txResponse = await transaction();
Expand All @@ -68,6 +72,7 @@ export async function getBalanceChange(
}

const txReceipt = await txResponse.wait();
assertIsNotNull(txReceipt, "txReceipt");
const txBlockNumber = txReceipt.blockNumber;

const block = await provider.send("eth_getBlockByHash", [
Expand All @@ -83,23 +88,26 @@ export async function getBalanceChange(

const address = await getAddressOf(account);

const balanceAfter = await provider.send("eth_getBalance", [
const balanceAfterHex = await provider.send("eth_getBalance", [
address,
`0x${txBlockNumber.toString(16)}`,
]);

const balanceBefore = await provider.send("eth_getBalance", [
const balanceBeforeHex = await provider.send("eth_getBalance", [
address,
`0x${(txBlockNumber - 1).toString(16)}`,
]);

const balanceAfter = BigInt(balanceAfterHex);
const balanceBefore = BigInt(balanceBeforeHex);

if (options?.includeFee !== true && address === txResponse.from) {
const gasPrice = txReceipt.effectiveGasPrice ?? txResponse.gasPrice;
const gasPrice = txReceipt.gasPrice;
const gasUsed = txReceipt.gasUsed;
const txFee = gasPrice.mul(gasUsed);
const txFee = gasPrice * gasUsed;

return BigNumber.from(balanceAfter).add(txFee).sub(balanceBefore);
return balanceAfter + txFee - balanceBefore;
} else {
return BigNumber.from(balanceAfter).sub(balanceBefore);
return balanceAfter - balanceBefore;
}
}
51 changes: 26 additions & 25 deletions packages/hardhat-chai-matchers/src/internal/changeEtherBalances.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
import type { BigNumber, BigNumberish, providers } from "ethers";
import type EthersT from "ethers";
import type { Addressable, BigNumberish, TransactionResponse } from "ethers";
import ordinal from "ordinal";

import { buildAssert } from "../utils";
import { getAddressOf, Account } from "./misc/account";
import { getAddressOf } from "./misc/account";
import {
BalanceChangeOptions,
getAddresses,
getBalances,
} from "./misc/balance";
import { assertIsNotNull } from "./utils";

export function supportChangeEtherBalances(Assertion: Chai.AssertionStatic) {
Assertion.addMethod(
"changeEtherBalances",
function (
this: any,
accounts: Array<Account | string>,
accounts: Array<Addressable | string>,
balanceChanges: BigNumberish[],
options?: BalanceChangeOptions
) {
const { BigNumber } = require("ethers");

const { toBigInt } = require("ethers") as typeof EthersT;
// capture negated flag before async code executes; see buildAssert's jsdoc
const negated = this.__flags.negate;

Expand All @@ -29,19 +30,19 @@ export function supportChangeEtherBalances(Assertion: Chai.AssertionStatic) {
}

const checkBalanceChanges = ([actualChanges, accountAddresses]: [
Array<typeof BigNumber>,
bigint[],
string[]
]) => {
const assert = buildAssert(negated, checkBalanceChanges);

assert(
actualChanges.every((change, ind) =>
change.eq(BigNumber.from(balanceChanges[ind]))
actualChanges.every(
(change, ind) => change === toBigInt(balanceChanges[ind])
),
() => {
const lines: string[] = [];
actualChanges.forEach((change: BigNumber, i) => {
if (!change.eq(BigNumber.from(balanceChanges[i]))) {
actualChanges.forEach((change: bigint, i) => {
if (change !== toBigInt(balanceChanges[i])) {
lines.push(
`Expected the ether balance of ${
accountAddresses[i]
Expand All @@ -57,8 +58,8 @@ export function supportChangeEtherBalances(Assertion: Chai.AssertionStatic) {
},
() => {
const lines: string[] = [];
actualChanges.forEach((change: BigNumber, i) => {
if (change.eq(BigNumber.from(balanceChanges[i]))) {
actualChanges.forEach((change: bigint, i) => {
if (change === toBigInt(balanceChanges[i])) {
lines.push(
`Expected the ether balance of ${
accountAddresses[i]
Expand Down Expand Up @@ -88,47 +89,47 @@ export function supportChangeEtherBalances(Assertion: Chai.AssertionStatic) {
}

export async function getBalanceChanges(
transaction:
| providers.TransactionResponse
| Promise<providers.TransactionResponse>,
accounts: Array<Account | string>,
transaction: TransactionResponse | Promise<TransactionResponse>,
accounts: Array<Addressable | string>,
options?: BalanceChangeOptions
) {
): Promise<bigint[]> {
const txResponse = await transaction;

const txReceipt = await txResponse.wait();
assertIsNotNull(txReceipt, "txReceipt");
const txBlockNumber = txReceipt.blockNumber;

const balancesAfter = await getBalances(accounts, txBlockNumber);
const balancesBefore = await getBalances(accounts, txBlockNumber - 1);

const txFees = await getTxFees(accounts, txResponse, options);

return balancesAfter.map((balance, ind) =>
balance.add(txFees[ind]).sub(balancesBefore[ind])
return balancesAfter.map(
(balance, ind) => balance + txFees[ind] - balancesBefore[ind]
);
}

async function getTxFees(
accounts: Array<Account | string>,
txResponse: providers.TransactionResponse,
accounts: Array<Addressable | string>,
txResponse: TransactionResponse,
options?: BalanceChangeOptions
) {
): Promise<bigint[]> {
return Promise.all(
accounts.map(async (account) => {
if (
options?.includeFee !== true &&
(await getAddressOf(account)) === txResponse.from
) {
const txReceipt = await txResponse.wait();
const gasPrice = txReceipt.effectiveGasPrice ?? txResponse.gasPrice;
assertIsNotNull(txReceipt, "txReceipt");
const gasPrice = txReceipt.gasPrice ?? txResponse.gasPrice;
const gasUsed = txReceipt.gasUsed;
const txFee = gasPrice.mul(gasUsed);
const txFee = gasPrice * gasUsed;

return txFee;
}

return 0;
return 0n;
})
);
}
Loading

0 comments on commit a5b0033

Please sign in to comment.