@nomicfoundation/hardhat-ethers-chai-matchers 3.0.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +9 -0
- package/README.md +52 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +16 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/internal/add-chai-matchers.d.ts +2 -0
- package/dist/src/internal/add-chai-matchers.d.ts.map +1 -0
- package/dist/src/internal/add-chai-matchers.js +41 -0
- package/dist/src/internal/add-chai-matchers.js.map +1 -0
- package/dist/src/internal/constants.d.ts +13 -0
- package/dist/src/internal/constants.d.ts.map +1 -0
- package/dist/src/internal/constants.js +13 -0
- package/dist/src/internal/constants.js.map +1 -0
- package/dist/src/internal/hook-handlers/network.d.ts +4 -0
- package/dist/src/internal/hook-handlers/network.d.ts.map +1 -0
- package/dist/src/internal/hook-handlers/network.js +15 -0
- package/dist/src/internal/hook-handlers/network.js.map +1 -0
- package/dist/src/internal/matchers/addressable.d.ts +2 -0
- package/dist/src/internal/matchers/addressable.d.ts.map +1 -0
- package/dist/src/internal/matchers/addressable.js +53 -0
- package/dist/src/internal/matchers/addressable.js.map +1 -0
- package/dist/src/internal/matchers/big-number.d.ts +2 -0
- package/dist/src/internal/matchers/big-number.d.ts.map +1 -0
- package/dist/src/internal/matchers/big-number.js +178 -0
- package/dist/src/internal/matchers/big-number.js.map +1 -0
- package/dist/src/internal/matchers/changeEtherBalance.d.ts +7 -0
- package/dist/src/internal/matchers/changeEtherBalance.d.ts.map +1 -0
- package/dist/src/internal/matchers/changeEtherBalance.js +77 -0
- package/dist/src/internal/matchers/changeEtherBalance.js.map +1 -0
- package/dist/src/internal/matchers/changeEtherBalances.d.ts +7 -0
- package/dist/src/internal/matchers/changeEtherBalances.d.ts.map +1 -0
- package/dist/src/internal/matchers/changeEtherBalances.js +96 -0
- package/dist/src/internal/matchers/changeEtherBalances.js.map +1 -0
- package/dist/src/internal/matchers/changeTokenBalance.d.ts +16 -0
- package/dist/src/internal/matchers/changeTokenBalance.d.ts.map +1 -0
- package/dist/src/internal/matchers/changeTokenBalance.js +148 -0
- package/dist/src/internal/matchers/changeTokenBalance.js.map +1 -0
- package/dist/src/internal/matchers/emit.d.ts +5 -0
- package/dist/src/internal/matchers/emit.d.ts.map +1 -0
- package/dist/src/internal/matchers/emit.js +122 -0
- package/dist/src/internal/matchers/emit.js.map +1 -0
- package/dist/src/internal/matchers/hexEqual.d.ts +2 -0
- package/dist/src/internal/matchers/hexEqual.d.ts.map +1 -0
- package/dist/src/internal/matchers/hexEqual.js +19 -0
- package/dist/src/internal/matchers/hexEqual.js.map +1 -0
- package/dist/src/internal/matchers/properAddress.d.ts +2 -0
- package/dist/src/internal/matchers/properAddress.d.ts.map +1 -0
- package/dist/src/internal/matchers/properAddress.js +7 -0
- package/dist/src/internal/matchers/properAddress.js.map +1 -0
- package/dist/src/internal/matchers/properHex.d.ts +2 -0
- package/dist/src/internal/matchers/properHex.d.ts.map +1 -0
- package/dist/src/internal/matchers/properHex.js +13 -0
- package/dist/src/internal/matchers/properHex.js.map +1 -0
- package/dist/src/internal/matchers/properPrivateKey.d.ts +2 -0
- package/dist/src/internal/matchers/properPrivateKey.d.ts.map +1 -0
- package/dist/src/internal/matchers/properPrivateKey.js +7 -0
- package/dist/src/internal/matchers/properPrivateKey.js.map +1 -0
- package/dist/src/internal/matchers/reverted/panic.d.ts +13 -0
- package/dist/src/internal/matchers/reverted/panic.d.ts.map +1 -0
- package/dist/src/internal/matchers/reverted/panic.js +36 -0
- package/dist/src/internal/matchers/reverted/panic.js.map +1 -0
- package/dist/src/internal/matchers/reverted/reverted.d.ts +2 -0
- package/dist/src/internal/matchers/reverted/reverted.d.ts.map +1 -0
- package/dist/src/internal/matchers/reverted/reverted.js +112 -0
- package/dist/src/internal/matchers/reverted/reverted.js.map +1 -0
- package/dist/src/internal/matchers/reverted/revertedWith.d.ts +2 -0
- package/dist/src/internal/matchers/reverted/revertedWith.d.ts.map +1 -0
- package/dist/src/internal/matchers/reverted/revertedWith.js +56 -0
- package/dist/src/internal/matchers/reverted/revertedWith.js.map +1 -0
- package/dist/src/internal/matchers/reverted/revertedWithCustomError.d.ts +5 -0
- package/dist/src/internal/matchers/reverted/revertedWithCustomError.d.ts.map +1 -0
- package/dist/src/internal/matchers/reverted/revertedWithCustomError.js +120 -0
- package/dist/src/internal/matchers/reverted/revertedWithCustomError.js.map +1 -0
- package/dist/src/internal/matchers/reverted/revertedWithPanic.d.ts +2 -0
- package/dist/src/internal/matchers/reverted/revertedWithPanic.d.ts.map +1 -0
- package/dist/src/internal/matchers/reverted/revertedWithPanic.js +74 -0
- package/dist/src/internal/matchers/reverted/revertedWithPanic.js.map +1 -0
- package/dist/src/internal/matchers/reverted/revertedWithoutReason.d.ts +2 -0
- package/dist/src/internal/matchers/reverted/revertedWithoutReason.d.ts.map +1 -0
- package/dist/src/internal/matchers/reverted/revertedWithoutReason.js +41 -0
- package/dist/src/internal/matchers/reverted/revertedWithoutReason.js.map +1 -0
- package/dist/src/internal/matchers/reverted/utils.d.ts +39 -0
- package/dist/src/internal/matchers/reverted/utils.d.ts.map +1 -0
- package/dist/src/internal/matchers/reverted/utils.js +108 -0
- package/dist/src/internal/matchers/reverted/utils.js.map +1 -0
- package/dist/src/internal/matchers/withArgs.d.ts +16 -0
- package/dist/src/internal/matchers/withArgs.d.ts.map +1 -0
- package/dist/src/internal/matchers/withArgs.js +88 -0
- package/dist/src/internal/matchers/withArgs.js.map +1 -0
- package/dist/src/internal/utils/account.d.ts +3 -0
- package/dist/src/internal/utils/account.d.ts.map +1 -0
- package/dist/src/internal/utils/account.js +15 -0
- package/dist/src/internal/utils/account.js.map +1 -0
- package/dist/src/internal/utils/asserts.d.ts +5 -0
- package/dist/src/internal/utils/asserts.d.ts.map +1 -0
- package/dist/src/internal/utils/asserts.js +73 -0
- package/dist/src/internal/utils/asserts.js.map +1 -0
- package/dist/src/internal/utils/balance.d.ts +8 -0
- package/dist/src/internal/utils/balance.d.ts.map +1 -0
- package/dist/src/internal/utils/balance.js +19 -0
- package/dist/src/internal/utils/balance.js.map +1 -0
- package/dist/src/internal/utils/bigint.d.ts +2 -0
- package/dist/src/internal/utils/bigint.d.ts.map +1 -0
- package/dist/src/internal/utils/bigint.js +4 -0
- package/dist/src/internal/utils/bigint.js.map +1 -0
- package/dist/src/internal/utils/build-assert.d.ts +19 -0
- package/dist/src/internal/utils/build-assert.d.ts.map +1 -0
- package/dist/src/internal/utils/build-assert.js +39 -0
- package/dist/src/internal/utils/build-assert.js.map +1 -0
- package/dist/src/internal/utils/ordinal.d.ts +8 -0
- package/dist/src/internal/utils/ordinal.d.ts.map +1 -0
- package/dist/src/internal/utils/ordinal.js +21 -0
- package/dist/src/internal/utils/ordinal.js.map +1 -0
- package/dist/src/internal/utils/prevent-chaining.d.ts +2 -0
- package/dist/src/internal/utils/prevent-chaining.d.ts.map +1 -0
- package/dist/src/internal/utils/prevent-chaining.js +17 -0
- package/dist/src/internal/utils/prevent-chaining.js.map +1 -0
- package/dist/src/internal/utils/ssfi.d.ts +4 -0
- package/dist/src/internal/utils/ssfi.d.ts.map +1 -0
- package/dist/src/internal/utils/ssfi.js +2 -0
- package/dist/src/internal/utils/ssfi.js.map +1 -0
- package/dist/src/internal/utils/typed.d.ts +2 -0
- package/dist/src/internal/utils/typed.d.ts.map +1 -0
- package/dist/src/internal/utils/typed.js +10 -0
- package/dist/src/internal/utils/typed.js.map +1 -0
- package/dist/src/panic.d.ts +2 -0
- package/dist/src/panic.d.ts.map +1 -0
- package/dist/src/panic.js +2 -0
- package/dist/src/panic.js.map +1 -0
- package/dist/src/type-extensions.d.ts +45 -0
- package/dist/src/type-extensions.d.ts.map +1 -0
- package/dist/src/type-extensions.js +2 -0
- package/dist/src/type-extensions.js.map +1 -0
- package/dist/src/withArgs.d.ts +2 -0
- package/dist/src/withArgs.d.ts.map +1 -0
- package/dist/src/withArgs.js +2 -0
- package/dist/src/withArgs.js.map +1 -0
- package/package.json +85 -0
- package/src/index.ts +21 -0
- package/src/internal/add-chai-matchers.ts +46 -0
- package/src/internal/constants.ts +13 -0
- package/src/internal/hook-handlers/network.ts +24 -0
- package/src/internal/matchers/addressable.ts +86 -0
- package/src/internal/matchers/big-number.ts +279 -0
- package/src/internal/matchers/changeEtherBalance.ts +138 -0
- package/src/internal/matchers/changeEtherBalances.ts +188 -0
- package/src/internal/matchers/changeTokenBalance.ts +295 -0
- package/src/internal/matchers/emit.ts +232 -0
- package/src/internal/matchers/hexEqual.ts +29 -0
- package/src/internal/matchers/properAddress.ts +12 -0
- package/src/internal/matchers/properHex.ts +29 -0
- package/src/internal/matchers/properPrivateKey.ts +12 -0
- package/src/internal/matchers/reverted/panic.ts +36 -0
- package/src/internal/matchers/reverted/reverted.ts +165 -0
- package/src/internal/matchers/reverted/revertedWith.ts +100 -0
- package/src/internal/matchers/reverted/revertedWithCustomError.ts +243 -0
- package/src/internal/matchers/reverted/revertedWithPanic.ts +118 -0
- package/src/internal/matchers/reverted/revertedWithoutReason.ts +73 -0
- package/src/internal/matchers/reverted/utils.ts +147 -0
- package/src/internal/matchers/withArgs.ts +139 -0
- package/src/internal/utils/account.ts +24 -0
- package/src/internal/utils/asserts.ts +156 -0
- package/src/internal/utils/balance.ts +39 -0
- package/src/internal/utils/bigint.ts +3 -0
- package/src/internal/utils/build-assert.ts +54 -0
- package/src/internal/utils/ordinal.ts +24 -0
- package/src/internal/utils/prevent-chaining.ts +33 -0
- package/src/internal/utils/ssfi.ts +6 -0
- package/src/internal/utils/typed.ts +9 -0
- package/src/panic.ts +1 -0
- package/src/type-extensions.ts +82 -0
- package/src/withArgs.ts +1 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
import { HardhatError } from "@nomicfoundation/hardhat-errors";
|
2
|
+
import { numberToHexString } from "@nomicfoundation/hardhat-utils/hex";
|
3
|
+
import { REVERTED_MATCHER } from "../../constants.js";
|
4
|
+
import { assertIsNotNull } from "../../utils/asserts.js";
|
5
|
+
import { buildAssert } from "../../utils/build-assert.js";
|
6
|
+
import { preventAsyncMatcherChaining } from "../../utils/prevent-chaining.js";
|
7
|
+
import { decodeReturnData, getReturnDataFromError, parseBytes32String, } from "./utils.js";
|
8
|
+
export function supportReverted(Assertion, chaiUtils) {
|
9
|
+
Assertion.addMethod(REVERTED_MATCHER, function (ethers) {
|
10
|
+
// capture negated flag before async code executes; see buildAssert's jsdoc
|
11
|
+
const negated = this.__flags.negate;
|
12
|
+
const subject = this._obj;
|
13
|
+
preventAsyncMatcherChaining(this, REVERTED_MATCHER, chaiUtils);
|
14
|
+
// Check if the received value can be linked to a transaction, and then
|
15
|
+
// get the receipt of that transaction and check its status.
|
16
|
+
//
|
17
|
+
// If the value doesn't correspond to a transaction, then the `reverted`
|
18
|
+
// assertion is false.
|
19
|
+
const onSuccess = async (value) => {
|
20
|
+
const assert = buildAssert(negated, onSuccess);
|
21
|
+
if (isTransactionResponse(value) || typeof value === "string") {
|
22
|
+
const hash = typeof value === "string" ? value : value.hash;
|
23
|
+
if (!isValidTransactionHash(hash)) {
|
24
|
+
throw new HardhatError(HardhatError.ERRORS.CHAI_MATCHERS.EXPECTED_VALID_TRANSACTION_HASH, {
|
25
|
+
hash,
|
26
|
+
});
|
27
|
+
}
|
28
|
+
const receipt = await getTransactionReceipt(ethers, hash);
|
29
|
+
if (receipt === null) {
|
30
|
+
// If the receipt is null, maybe the string is a bytes32 string
|
31
|
+
if (isBytes32String(hash)) {
|
32
|
+
assert(false, "Expected transaction to be reverted");
|
33
|
+
return;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
assertIsNotNull(receipt, "receipt");
|
37
|
+
assert(receipt.status === 0, "Expected transaction to be reverted", "Expected transaction NOT to be reverted");
|
38
|
+
}
|
39
|
+
else if (isTransactionReceipt(value)) {
|
40
|
+
const receipt = value;
|
41
|
+
assert(receipt.status === 0, "Expected transaction to be reverted", "Expected transaction NOT to be reverted");
|
42
|
+
}
|
43
|
+
else {
|
44
|
+
// If the subject of the assertion is not connected to a transaction
|
45
|
+
// (hash, receipt, etc.), then the assertion fails.
|
46
|
+
// Since we use `false` here, this means that `.not.to.be.reverted`
|
47
|
+
// assertions will pass instead of always throwing a validation error.
|
48
|
+
// This allows users to do things like:
|
49
|
+
// `expect(c.callStatic.f()).to.not.be.reverted`
|
50
|
+
assert(false, "Expected transaction to be reverted");
|
51
|
+
}
|
52
|
+
};
|
53
|
+
const onError = (error) => {
|
54
|
+
const assert = buildAssert(negated, onError);
|
55
|
+
const returnData = getReturnDataFromError(error);
|
56
|
+
const decodedReturnData = decodeReturnData(returnData);
|
57
|
+
if (decodedReturnData.kind === "Empty" ||
|
58
|
+
decodedReturnData.kind === "Custom") {
|
59
|
+
// in the negated case, if we can't decode the reason, we just indicate
|
60
|
+
// that the transaction didn't revert
|
61
|
+
assert(true, undefined, `Expected transaction NOT to be reverted`);
|
62
|
+
}
|
63
|
+
else if (decodedReturnData.kind === "Error") {
|
64
|
+
assert(true, undefined, `Expected transaction NOT to be reverted, but it reverted with reason '${decodedReturnData.reason}'`);
|
65
|
+
}
|
66
|
+
else if (decodedReturnData.kind === "Panic") {
|
67
|
+
assert(true, undefined, `Expected transaction NOT to be reverted, but it reverted with panic code ${numberToHexString(decodedReturnData.code)} (${decodedReturnData.description})`);
|
68
|
+
}
|
69
|
+
else {
|
70
|
+
const _exhaustiveCheck = decodedReturnData;
|
71
|
+
}
|
72
|
+
};
|
73
|
+
// we use `Promise.resolve(subject)` so we can process both values and
|
74
|
+
// promises of values in the same way
|
75
|
+
const derivedPromise = Promise.resolve(subject).then(onSuccess, onError);
|
76
|
+
this.then = derivedPromise.then.bind(derivedPromise);
|
77
|
+
this.catch = derivedPromise.catch.bind(derivedPromise);
|
78
|
+
return this;
|
79
|
+
});
|
80
|
+
}
|
81
|
+
async function getTransactionReceipt(ethers, hash) {
|
82
|
+
return ethers.provider.getTransactionReceipt(hash);
|
83
|
+
}
|
84
|
+
function isTransactionResponse(x) {
|
85
|
+
if (typeof x === "object" && x !== null) {
|
86
|
+
return "hash" in x;
|
87
|
+
}
|
88
|
+
return false;
|
89
|
+
}
|
90
|
+
function isTransactionReceipt(x) {
|
91
|
+
if (typeof x === "object" && x !== null && "status" in x) {
|
92
|
+
const status = x.status;
|
93
|
+
// this means we only support ethers's receipts for now; adding support for
|
94
|
+
// raw receipts, where the status is an hexadecimal string, should be easy
|
95
|
+
// and we can do it if there's demand for that
|
96
|
+
return typeof status === "number";
|
97
|
+
}
|
98
|
+
return false;
|
99
|
+
}
|
100
|
+
function isValidTransactionHash(x) {
|
101
|
+
return /0x[0-9a-fA-F]{64}/.test(x);
|
102
|
+
}
|
103
|
+
function isBytes32String(v) {
|
104
|
+
try {
|
105
|
+
parseBytes32String(v);
|
106
|
+
return true;
|
107
|
+
}
|
108
|
+
catch {
|
109
|
+
return false;
|
110
|
+
}
|
111
|
+
}
|
112
|
+
//# sourceMappingURL=reverted.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"reverted.js","sourceRoot":"","sources":["../../../../../src/internal/matchers/reverted/reverted.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"revertedWith.d.ts","sourceRoot":"","sources":["../../../../../src/internal/matchers/reverted/revertedWith.ts"],"names":[],"mappings":"AASA,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,IAAI,CAAC,eAAe,EAC/B,SAAS,EAAE,IAAI,CAAC,SAAS,GACxB,IAAI,CAuFN"}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import { HardhatError } from "@nomicfoundation/hardhat-errors";
|
2
|
+
import { numberToHexString } from "@nomicfoundation/hardhat-utils/hex";
|
3
|
+
import { REVERTED_WITH_MATCHER } from "../../constants.js";
|
4
|
+
import { buildAssert } from "../../utils/build-assert.js";
|
5
|
+
import { preventAsyncMatcherChaining } from "../../utils/prevent-chaining.js";
|
6
|
+
import { decodeReturnData, getReturnDataFromError } from "./utils.js";
|
7
|
+
export function supportRevertedWith(Assertion, chaiUtils) {
|
8
|
+
Assertion.addMethod(REVERTED_WITH_MATCHER, function (expectedReason) {
|
9
|
+
// capture negated flag before async code executes; see buildAssert's jsdoc
|
10
|
+
const negated = this.__flags.negate;
|
11
|
+
// validate expected reason
|
12
|
+
if (!(expectedReason instanceof RegExp) &&
|
13
|
+
typeof expectedReason !== "string") {
|
14
|
+
// if the input validation fails, we discard the subject since it could
|
15
|
+
// potentially be a rejected promise
|
16
|
+
Promise.resolve(this._obj).catch(() => { });
|
17
|
+
throw new HardhatError(HardhatError.ERRORS.CHAI_MATCHERS.EXPECT_STRING_OR_REGEX_AS_REVERT_REASON);
|
18
|
+
}
|
19
|
+
const expectedReasonString = expectedReason instanceof RegExp
|
20
|
+
? expectedReason.source
|
21
|
+
: expectedReason;
|
22
|
+
preventAsyncMatcherChaining(this, REVERTED_WITH_MATCHER, chaiUtils);
|
23
|
+
const onSuccess = () => {
|
24
|
+
const assert = buildAssert(negated, onSuccess);
|
25
|
+
assert(false, `Expected transaction to be reverted with reason '${expectedReasonString}', but it didn't revert`);
|
26
|
+
};
|
27
|
+
const onError = (error) => {
|
28
|
+
const assert = buildAssert(negated, onError);
|
29
|
+
const returnData = getReturnDataFromError(error);
|
30
|
+
const decodedReturnData = decodeReturnData(returnData);
|
31
|
+
if (decodedReturnData.kind === "Empty") {
|
32
|
+
assert(false, `Expected transaction to be reverted with reason '${expectedReasonString}', but it reverted without a reason`);
|
33
|
+
}
|
34
|
+
else if (decodedReturnData.kind === "Error") {
|
35
|
+
const matchesExpectedReason = expectedReason instanceof RegExp
|
36
|
+
? expectedReason.test(decodedReturnData.reason)
|
37
|
+
: decodedReturnData.reason === expectedReasonString;
|
38
|
+
assert(matchesExpectedReason, `Expected transaction to be reverted with reason '${expectedReasonString}', but it reverted with reason '${decodedReturnData.reason}'`, `Expected transaction NOT to be reverted with reason '${expectedReasonString}', but it was`);
|
39
|
+
}
|
40
|
+
else if (decodedReturnData.kind === "Panic") {
|
41
|
+
assert(false, `Expected transaction to be reverted with reason '${expectedReasonString}', but it reverted with panic code ${numberToHexString(decodedReturnData.code)} (${decodedReturnData.description})`);
|
42
|
+
}
|
43
|
+
else if (decodedReturnData.kind === "Custom") {
|
44
|
+
assert(false, `Expected transaction to be reverted with reason '${expectedReasonString}', but it reverted with a custom error`);
|
45
|
+
}
|
46
|
+
else {
|
47
|
+
const _exhaustiveCheck = decodedReturnData;
|
48
|
+
}
|
49
|
+
};
|
50
|
+
const derivedPromise = Promise.resolve(this._obj).then(onSuccess, onError);
|
51
|
+
this.then = derivedPromise.then.bind(derivedPromise);
|
52
|
+
this.catch = derivedPromise.catch.bind(derivedPromise);
|
53
|
+
return this;
|
54
|
+
});
|
55
|
+
}
|
56
|
+
//# sourceMappingURL=revertedWith.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"revertedWith.js","sourceRoot":"","sources":["../../../../../src/internal/matchers/reverted/revertedWith.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,5 @@
|
|
1
|
+
import type { Ssfi } from "../../utils/ssfi.js";
|
2
|
+
export declare const REVERTED_WITH_CUSTOM_ERROR_CALLED = "customErrorAssertionCalled";
|
3
|
+
export declare function supportRevertedWithCustomError(Assertion: Chai.AssertionStatic, chaiUtils: Chai.ChaiUtils): void;
|
4
|
+
export declare function revertedWithCustomErrorWithArgs(context: any, Assertion: Chai.AssertionStatic, _chaiUtils: Chai.ChaiUtils, expectedArgs: any[], ssfi: Ssfi): Promise<void>;
|
5
|
+
//# sourceMappingURL=revertedWithCustomError.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"revertedWithCustomError.d.ts","sourceRoot":"","sources":["../../../../../src/internal/matchers/reverted/revertedWithCustomError.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAqBhD,eAAO,MAAM,iCAAiC,+BAA+B,CAAC;AAQ9E,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,IAAI,CAAC,eAAe,EAC/B,SAAS,EAAE,IAAI,CAAC,SAAS,GACxB,IAAI,CAqHN;AAqDD,wBAAsB,+BAA+B,CACnD,OAAO,EAAE,GAAG,EACZ,SAAS,EAAE,IAAI,CAAC,eAAe,EAC/B,UAAU,EAAE,IAAI,CAAC,SAAS,EAC1B,YAAY,EAAE,GAAG,EAAE,EACnB,IAAI,EAAE,IAAI,GACT,OAAO,CAAC,IAAI,CAAC,CAkCf"}
|
@@ -0,0 +1,120 @@
|
|
1
|
+
import { HardhatError } from "@nomicfoundation/hardhat-errors";
|
2
|
+
import { numberToHexString } from "@nomicfoundation/hardhat-utils/hex";
|
3
|
+
import { ASSERTION_ABORTED, REVERTED_WITH_CUSTOM_ERROR_MATCHER, } from "../../constants.js";
|
4
|
+
import { assertArgsArraysEqual, assertIsNotNull } from "../../utils/asserts.js";
|
5
|
+
import { buildAssert } from "../../utils/build-assert.js";
|
6
|
+
import { preventAsyncMatcherChaining } from "../../utils/prevent-chaining.js";
|
7
|
+
import { decodeReturnData, getReturnDataFromError, resultToArray, } from "./utils.js";
|
8
|
+
export const REVERTED_WITH_CUSTOM_ERROR_CALLED = "customErrorAssertionCalled";
|
9
|
+
export function supportRevertedWithCustomError(Assertion, chaiUtils) {
|
10
|
+
Assertion.addMethod(REVERTED_WITH_CUSTOM_ERROR_MATCHER, function (contract, expectedCustomErrorName, ...args) {
|
11
|
+
// capture negated flag before async code executes; see buildAssert's jsdoc
|
12
|
+
const negated = this.__flags.negate;
|
13
|
+
const { iface, expectedCustomError } = validateInput(this._obj, contract, expectedCustomErrorName, args);
|
14
|
+
preventAsyncMatcherChaining(this, REVERTED_WITH_CUSTOM_ERROR_MATCHER, chaiUtils);
|
15
|
+
const onSuccess = () => {
|
16
|
+
if (chaiUtils.flag(this, ASSERTION_ABORTED) === true) {
|
17
|
+
return;
|
18
|
+
}
|
19
|
+
const assert = buildAssert(negated, onSuccess);
|
20
|
+
assert(false, `Expected transaction to be reverted with custom error '${expectedCustomErrorName}', but it didn't revert`);
|
21
|
+
};
|
22
|
+
const onError = (error) => {
|
23
|
+
if (chaiUtils.flag(this, ASSERTION_ABORTED) === true) {
|
24
|
+
return;
|
25
|
+
}
|
26
|
+
const assert = buildAssert(negated, onError);
|
27
|
+
const returnData = getReturnDataFromError(error);
|
28
|
+
const decodedReturnData = decodeReturnData(returnData);
|
29
|
+
if (decodedReturnData.kind === "Empty") {
|
30
|
+
assert(false, `Expected transaction to be reverted with custom error '${expectedCustomErrorName}', but it reverted without a reason`);
|
31
|
+
}
|
32
|
+
else if (decodedReturnData.kind === "Error") {
|
33
|
+
assert(false, `Expected transaction to be reverted with custom error '${expectedCustomErrorName}', but it reverted with reason '${decodedReturnData.reason}'`);
|
34
|
+
}
|
35
|
+
else if (decodedReturnData.kind === "Panic") {
|
36
|
+
assert(false, `Expected transaction to be reverted with custom error '${expectedCustomErrorName}', but it reverted with panic code ${numberToHexString(decodedReturnData.code)} (${decodedReturnData.description})`);
|
37
|
+
}
|
38
|
+
else if (decodedReturnData.kind === "Custom") {
|
39
|
+
if (decodedReturnData.id === expectedCustomError.selector) {
|
40
|
+
// add flag with the data needed for .withArgs
|
41
|
+
const customErrorAssertionData = {
|
42
|
+
contractInterface: iface,
|
43
|
+
customError: expectedCustomError,
|
44
|
+
returnData,
|
45
|
+
};
|
46
|
+
this.customErrorData = customErrorAssertionData;
|
47
|
+
assert(true, undefined, `Expected transaction NOT to be reverted with custom error '${expectedCustomErrorName}', but it was`);
|
48
|
+
}
|
49
|
+
else {
|
50
|
+
// try to decode the actual custom error
|
51
|
+
// this will only work when the error comes from the given contract
|
52
|
+
const actualCustomError = iface.getError(decodedReturnData.id);
|
53
|
+
if (actualCustomError === null) {
|
54
|
+
assert(false, `Expected transaction to be reverted with custom error '${expectedCustomErrorName}', but it reverted with a different custom error`);
|
55
|
+
}
|
56
|
+
else {
|
57
|
+
assert(false, `Expected transaction to be reverted with custom error '${expectedCustomErrorName}', but it reverted with custom error '${actualCustomError.name}'`);
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
else {
|
62
|
+
const _exhaustiveCheck = decodedReturnData;
|
63
|
+
}
|
64
|
+
};
|
65
|
+
const derivedPromise = Promise.resolve(this._obj).then(onSuccess, onError);
|
66
|
+
// needed for .withArgs
|
67
|
+
chaiUtils.flag(this, REVERTED_WITH_CUSTOM_ERROR_CALLED, true);
|
68
|
+
this.promise = derivedPromise;
|
69
|
+
this.then = derivedPromise.then.bind(derivedPromise);
|
70
|
+
this.catch = derivedPromise.catch.bind(derivedPromise);
|
71
|
+
return this;
|
72
|
+
});
|
73
|
+
}
|
74
|
+
function validateInput(obj, contract, expectedCustomErrorName, args) {
|
75
|
+
try {
|
76
|
+
// check the case where users forget to pass the contract as the first
|
77
|
+
// argument
|
78
|
+
if (typeof contract === "string" || contract?.interface === undefined) {
|
79
|
+
// discard subject since it could potentially be a rejected promise
|
80
|
+
throw new HardhatError(HardhatError.ERRORS.CHAI_MATCHERS.FIRST_ARGUMENT_MUST_BE_A_CONTRACT);
|
81
|
+
}
|
82
|
+
// validate custom error name
|
83
|
+
if (typeof expectedCustomErrorName !== "string") {
|
84
|
+
throw new HardhatError(HardhatError.ERRORS.CHAI_MATCHERS.STRING_EXPECTED_AS_CUSTOM_ERROR_NAME);
|
85
|
+
}
|
86
|
+
const iface = contract.interface;
|
87
|
+
const expectedCustomError = iface.getError(expectedCustomErrorName);
|
88
|
+
// check that interface contains the given custom error
|
89
|
+
if (expectedCustomError === null) {
|
90
|
+
throw new HardhatError(HardhatError.ERRORS.CHAI_MATCHERS.CONTRACT_DOES_NOT_HAVE_CUSTOM_ERROR, {
|
91
|
+
customErrorName: expectedCustomErrorName,
|
92
|
+
});
|
93
|
+
}
|
94
|
+
if (args.length > 0) {
|
95
|
+
throw new HardhatError(HardhatError.ERRORS.CHAI_MATCHERS.REVERT_INVALID_ARGUMENTS_LENGTH);
|
96
|
+
}
|
97
|
+
return { iface, expectedCustomError };
|
98
|
+
}
|
99
|
+
catch (e) {
|
100
|
+
// if the input validation fails, we discard the subject since it could
|
101
|
+
// potentially be a rejected promise
|
102
|
+
Promise.resolve(obj).catch(() => { });
|
103
|
+
throw e;
|
104
|
+
}
|
105
|
+
}
|
106
|
+
export async function revertedWithCustomErrorWithArgs(context, Assertion, _chaiUtils, expectedArgs, ssfi) {
|
107
|
+
const negated = false; // .withArgs cannot be negated
|
108
|
+
const assert = buildAssert(negated, ssfi);
|
109
|
+
const customErrorAssertionData = context.customErrorData;
|
110
|
+
if (customErrorAssertionData === undefined) {
|
111
|
+
throw new HardhatError(HardhatError.ERRORS.CHAI_MATCHERS.WITH_ARGS_FORBIDDEN);
|
112
|
+
}
|
113
|
+
const { contractInterface, customError, returnData } = customErrorAssertionData;
|
114
|
+
const errorFragment = contractInterface.getError(customError.name);
|
115
|
+
assertIsNotNull(errorFragment, "errorFragment");
|
116
|
+
// We transform ether's Array-like object into an actual array as it's safer
|
117
|
+
const actualArgs = resultToArray(contractInterface.decodeErrorResult(errorFragment, returnData));
|
118
|
+
assertArgsArraysEqual(Assertion, expectedArgs, actualArgs, `"${customError.name}" custom error`, "error", assert, ssfi);
|
119
|
+
}
|
120
|
+
//# sourceMappingURL=revertedWithCustomError.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"revertedWithCustomError.js","sourceRoot":"","sources":["../../../../../src/internal/matchers/reverted/revertedWithCustomError.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAEvE,OAAO,EACL,iBAAiB,EACjB,kCAAkC,GACnC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAE9E,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,MAAM,iCAAiC,GAAG,4BAA4B,CAAC;AAQ9E,MAAM,UAAU,8BAA8B,CAC5C,SAA+B,EAC/B,SAAyB;IAEzB,SAAS,CAAC,SAAS,CACjB,kCAAkC,EAClC,UAEE,QAAsB,EACtB,uBAA+B,EAC/B,GAAG,IAAW;QAEd,2EAA2E;QAC3E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QAEpC,MAAM,EAAE,KAAK,EAAE,mBAAmB,EAAE,GAAG,aAAa,CAClD,IAAI,CAAC,IAAI,EACT,QAAQ,EACR,uBAAuB,EACvB,IAAI,CACL,CAAC;QAEF,2BAA2B,CACzB,IAAI,EACJ,kCAAkC,EAClC,SAAS,CACV,CAAC;QAEF,MAAM,SAAS,GAAG,GAAG,EAAE;YACrB,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,KAAK,IAAI,EAAE,CAAC;gBACrD,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAE/C,MAAM,CACJ,KAAK,EACL,0DAA0D,uBAAuB,yBAAyB,CAC3G,CAAC;QACJ,CAAC,CAAC;QAEF,MAAM,OAAO,GAAG,CAAC,KAAU,EAAE,EAAE;YAC7B,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,KAAK,IAAI,EAAE,CAAC;gBACrD,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAE7C,MAAM,UAAU,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;YACjD,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;YAEvD,IAAI,iBAAiB,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACvC,MAAM,CACJ,KAAK,EACL,0DAA0D,uBAAuB,qCAAqC,CACvH,CAAC;YACJ,CAAC;iBAAM,IAAI,iBAAiB,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC9C,MAAM,CACJ,KAAK,EACL,0DAA0D,uBAAuB,mCAAmC,iBAAiB,CAAC,MAAM,GAAG,CAChJ,CAAC;YACJ,CAAC;iBAAM,IAAI,iBAAiB,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC9C,MAAM,CACJ,KAAK,EACL,0DAA0D,uBAAuB,sCAAsC,iBAAiB,CACtI,iBAAiB,CAAC,IAAI,CACvB,KAAK,iBAAiB,CAAC,WAAW,GAAG,CACvC,CAAC;YACJ,CAAC;iBAAM,IAAI,iBAAiB,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC/C,IAAI,iBAAiB,CAAC,EAAE,KAAK,mBAAmB,CAAC,QAAQ,EAAE,CAAC;oBAC1D,8CAA8C;oBAC9C,MAAM,wBAAwB,GAA6B;wBACzD,iBAAiB,EAAE,KAAK;wBACxB,WAAW,EAAE,mBAAmB;wBAChC,UAAU;qBACX,CAAC;oBACF,IAAI,CAAC,eAAe,GAAG,wBAAwB,CAAC;oBAEhD,MAAM,CACJ,IAAI,EACJ,SAAS,EACT,8DAA8D,uBAAuB,eAAe,CACrG,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,wCAAwC;oBACxC,mEAAmE;oBACnE,MAAM,iBAAiB,GAAG,KAAK,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;oBAE/D,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;wBAC/B,MAAM,CACJ,KAAK,EACL,0DAA0D,uBAAuB,kDAAkD,CACpI,CAAC;oBACJ,CAAC;yBAAM,CAAC;wBACN,MAAM,CACJ,KAAK,EACL,0DAA0D,uBAAuB,yCAAyC,iBAAiB,CAAC,IAAI,GAAG,CACpJ,CAAC;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,gBAAgB,GAAU,iBAAiB,CAAC;YACpD,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CACpD,SAAS,EACT,OAAO,CACR,CAAC;QAEF,uBAAuB;QACvB,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,iCAAiC,EAAE,IAAI,CAAC,CAAC;QAC9D,IAAI,CAAC,OAAO,GAAG,cAAc,CAAC;QAE9B,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACrD,IAAI,CAAC,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAEvD,OAAO,IAAI,CAAC;IACd,CAAC,CACF,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CACpB,GAAQ,EACR,QAAsB,EACtB,uBAA+B,EAC/B,IAAW;IAEX,IAAI,CAAC;QACH,sEAAsE;QACtE,WAAW;QACX,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,EAAE,SAAS,KAAK,SAAS,EAAE,CAAC;YACtE,mEAAmE;YACnE,MAAM,IAAI,YAAY,CACpB,YAAY,CAAC,MAAM,CAAC,aAAa,CAAC,iCAAiC,CACpE,CAAC;QACJ,CAAC;QAED,6BAA6B;QAC7B,IAAI,OAAO,uBAAuB,KAAK,QAAQ,EAAE,CAAC;YAChD,MAAM,IAAI,YAAY,CACpB,YAAY,CAAC,MAAM,CAAC,aAAa,CAAC,oCAAoC,CACvE,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC;QACjC,MAAM,mBAAmB,GAAG,KAAK,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC;QAEpE,uDAAuD;QACvD,IAAI,mBAAmB,KAAK,IAAI,EAAE,CAAC;YACjC,MAAM,IAAI,YAAY,CACpB,YAAY,CAAC,MAAM,CAAC,aAAa,CAAC,mCAAmC,EACrE;gBACE,eAAe,EAAE,uBAAuB;aACzC,CACF,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,YAAY,CACpB,YAAY,CAAC,MAAM,CAAC,aAAa,CAAC,+BAA+B,CAClE,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC;IACxC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,uEAAuE;QACvE,oCAAoC;QACpC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACrC,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,OAAY,EACZ,SAA+B,EAC/B,UAA0B,EAC1B,YAAmB,EACnB,IAAU;IAEV,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,8BAA8B;IACrD,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAE1C,MAAM,wBAAwB,GAC5B,OAAO,CAAC,eAAe,CAAC;IAE1B,IAAI,wBAAwB,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,IAAI,YAAY,CACpB,YAAY,CAAC,MAAM,CAAC,aAAa,CAAC,mBAAmB,CACtD,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,GAClD,wBAAwB,CAAC;IAE3B,MAAM,aAAa,GAAG,iBAAiB,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAEnE,eAAe,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;IAEhD,4EAA4E;IAC5E,MAAM,UAAU,GAAG,aAAa,CAC9B,iBAAiB,CAAC,iBAAiB,CAAC,aAAa,EAAE,UAAU,CAAC,CAC/D,CAAC;IAEF,qBAAqB,CACnB,SAAS,EACT,YAAY,EACZ,UAAU,EACV,IAAI,WAAW,CAAC,IAAI,gBAAgB,EACpC,OAAO,EACP,MAAM,EACN,IAAI,CACL,CAAC;AACJ,CAAC"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"revertedWithPanic.d.ts","sourceRoot":"","sources":["../../../../../src/internal/matchers/reverted/revertedWithPanic.ts"],"names":[],"mappings":"AAWA,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,IAAI,CAAC,eAAe,EAC/B,SAAS,EAAE,IAAI,CAAC,SAAS,GACxB,IAAI,CAuGN"}
|
@@ -0,0 +1,74 @@
|
|
1
|
+
import { HardhatError } from "@nomicfoundation/hardhat-errors";
|
2
|
+
import { toBigInt } from "@nomicfoundation/hardhat-utils/bigint";
|
3
|
+
import { numberToHexString } from "@nomicfoundation/hardhat-utils/hex";
|
4
|
+
import { REVERTED_WITH_PANIC_MATCHER } from "../../constants.js";
|
5
|
+
import { buildAssert } from "../../utils/build-assert.js";
|
6
|
+
import { preventAsyncMatcherChaining } from "../../utils/prevent-chaining.js";
|
7
|
+
import { panicErrorCodeToReason } from "./panic.js";
|
8
|
+
import { decodeReturnData, getReturnDataFromError } from "./utils.js";
|
9
|
+
export function supportRevertedWithPanic(Assertion, chaiUtils) {
|
10
|
+
Assertion.addMethod(REVERTED_WITH_PANIC_MATCHER, function (expectedCodeArg) {
|
11
|
+
// capture negated flag before async code executes; see buildAssert's jsdoc
|
12
|
+
const negated = this.__flags.negate;
|
13
|
+
let expectedCode;
|
14
|
+
try {
|
15
|
+
if (expectedCodeArg !== undefined) {
|
16
|
+
expectedCode = toBigInt(expectedCodeArg);
|
17
|
+
}
|
18
|
+
}
|
19
|
+
catch {
|
20
|
+
// if the input validation fails, we discard the subject since it could
|
21
|
+
// potentially be a rejected promise
|
22
|
+
Promise.resolve(this._obj).catch(() => { });
|
23
|
+
throw new HardhatError(HardhatError.ERRORS.CHAI_MATCHERS.PANIC_CODE_EXPECTED, {
|
24
|
+
panicCode: expectedCodeArg,
|
25
|
+
});
|
26
|
+
}
|
27
|
+
const code = expectedCode;
|
28
|
+
let description;
|
29
|
+
let formattedPanicCode;
|
30
|
+
if (code === undefined) {
|
31
|
+
formattedPanicCode = "some panic code";
|
32
|
+
}
|
33
|
+
else {
|
34
|
+
const codeBN = toBigInt(code);
|
35
|
+
description = panicErrorCodeToReason(codeBN) ?? "unknown panic code";
|
36
|
+
formattedPanicCode = `panic code ${numberToHexString(codeBN)} (${description})`;
|
37
|
+
}
|
38
|
+
preventAsyncMatcherChaining(this, REVERTED_WITH_PANIC_MATCHER, chaiUtils);
|
39
|
+
const onSuccess = () => {
|
40
|
+
const assert = buildAssert(negated, onSuccess);
|
41
|
+
assert(false, `Expected transaction to be reverted with ${formattedPanicCode}, but it didn't revert`);
|
42
|
+
};
|
43
|
+
const onError = (error) => {
|
44
|
+
const assert = buildAssert(negated, onError);
|
45
|
+
const returnData = getReturnDataFromError(error);
|
46
|
+
const decodedReturnData = decodeReturnData(returnData);
|
47
|
+
if (decodedReturnData.kind === "Empty") {
|
48
|
+
assert(false, `Expected transaction to be reverted with ${formattedPanicCode}, but it reverted without a reason`);
|
49
|
+
}
|
50
|
+
else if (decodedReturnData.kind === "Error") {
|
51
|
+
assert(false, `Expected transaction to be reverted with ${formattedPanicCode}, but it reverted with reason '${decodedReturnData.reason}'`);
|
52
|
+
}
|
53
|
+
else if (decodedReturnData.kind === "Panic") {
|
54
|
+
if (code !== undefined) {
|
55
|
+
assert(decodedReturnData.code === code, `Expected transaction to be reverted with ${formattedPanicCode}, but it reverted with panic code ${numberToHexString(decodedReturnData.code)} (${decodedReturnData.description})`, `Expected transaction NOT to be reverted with ${formattedPanicCode}, but it was`);
|
56
|
+
}
|
57
|
+
else {
|
58
|
+
assert(true, undefined, `Expected transaction NOT to be reverted with ${formattedPanicCode}, but it reverted with panic code ${numberToHexString(decodedReturnData.code)} (${decodedReturnData.description})`);
|
59
|
+
}
|
60
|
+
}
|
61
|
+
else if (decodedReturnData.kind === "Custom") {
|
62
|
+
assert(false, `Expected transaction to be reverted with ${formattedPanicCode}, but it reverted with a custom error`);
|
63
|
+
}
|
64
|
+
else {
|
65
|
+
const _exhaustiveCheck = decodedReturnData;
|
66
|
+
}
|
67
|
+
};
|
68
|
+
const derivedPromise = Promise.resolve(this._obj).then(onSuccess, onError);
|
69
|
+
this.then = derivedPromise.then.bind(derivedPromise);
|
70
|
+
this.catch = derivedPromise.catch.bind(derivedPromise);
|
71
|
+
return this;
|
72
|
+
});
|
73
|
+
}
|
74
|
+
//# sourceMappingURL=revertedWithPanic.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"revertedWithPanic.js","sourceRoot":"","sources":["../../../../../src/internal/matchers/reverted/revertedWithPanic.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"revertedWithoutReason.d.ts","sourceRoot":"","sources":["../../../../../src/internal/matchers/reverted/revertedWithoutReason.ts"],"names":[],"mappings":"AAQA,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,IAAI,CAAC,eAAe,EAC/B,SAAS,EAAE,IAAI,CAAC,SAAS,GACxB,IAAI,CA6DN"}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import { numberToHexString } from "@nomicfoundation/hardhat-utils/hex";
|
2
|
+
import { REVERTED_WITHOUT_REASON_MATCHER } from "../../constants.js";
|
3
|
+
import { buildAssert } from "../../utils/build-assert.js";
|
4
|
+
import { preventAsyncMatcherChaining } from "../../utils/prevent-chaining.js";
|
5
|
+
import { decodeReturnData, getReturnDataFromError } from "./utils.js";
|
6
|
+
export function supportRevertedWithoutReason(Assertion, chaiUtils) {
|
7
|
+
Assertion.addMethod(REVERTED_WITHOUT_REASON_MATCHER, function () {
|
8
|
+
// capture negated flag before async code executes; see buildAssert's jsdoc
|
9
|
+
const negated = this.__flags.negate;
|
10
|
+
preventAsyncMatcherChaining(this, REVERTED_WITHOUT_REASON_MATCHER, chaiUtils);
|
11
|
+
const onSuccess = () => {
|
12
|
+
const assert = buildAssert(negated, onSuccess);
|
13
|
+
assert(false, `Expected transaction to be reverted without a reason, but it didn't revert`);
|
14
|
+
};
|
15
|
+
const onError = (error) => {
|
16
|
+
const assert = buildAssert(negated, onError);
|
17
|
+
const returnData = getReturnDataFromError(error);
|
18
|
+
const decodedReturnData = decodeReturnData(returnData);
|
19
|
+
if (decodedReturnData.kind === "Error") {
|
20
|
+
assert(false, `Expected transaction to be reverted without a reason, but it reverted with reason '${decodedReturnData.reason}'`);
|
21
|
+
}
|
22
|
+
else if (decodedReturnData.kind === "Empty") {
|
23
|
+
assert(true, undefined, "Expected transaction NOT to be reverted without a reason, but it was");
|
24
|
+
}
|
25
|
+
else if (decodedReturnData.kind === "Panic") {
|
26
|
+
assert(false, `Expected transaction to be reverted without a reason, but it reverted with panic code ${numberToHexString(decodedReturnData.code)} (${decodedReturnData.description})`);
|
27
|
+
}
|
28
|
+
else if (decodedReturnData.kind === "Custom") {
|
29
|
+
assert(false, `Expected transaction to be reverted without a reason, but it reverted with a custom error`);
|
30
|
+
}
|
31
|
+
else {
|
32
|
+
const _exhaustiveCheck = decodedReturnData;
|
33
|
+
}
|
34
|
+
};
|
35
|
+
const derivedPromise = Promise.resolve(this._obj).then(onSuccess, onError);
|
36
|
+
this.then = derivedPromise.then.bind(derivedPromise);
|
37
|
+
this.catch = derivedPromise.catch.bind(derivedPromise);
|
38
|
+
return this;
|
39
|
+
});
|
40
|
+
}
|
41
|
+
//# sourceMappingURL=revertedWithoutReason.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"revertedWithoutReason.js","sourceRoot":"","sources":["../../../../../src/internal/matchers/reverted/revertedWithoutReason.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAEvE,OAAO,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAE9E,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEtE,MAAM,UAAU,4BAA4B,CAC1C,SAA+B,EAC/B,SAAyB;IAEzB,SAAS,CAAC,SAAS,CAAC,+BAA+B,EAAE;QACnD,2EAA2E;QAC3E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QAEpC,2BAA2B,CACzB,IAAI,EACJ,+BAA+B,EAC/B,SAAS,CACV,CAAC;QAEF,MAAM,SAAS,GAAG,GAAG,EAAE;YACrB,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAE/C,MAAM,CACJ,KAAK,EACL,4EAA4E,CAC7E,CAAC;QACJ,CAAC,CAAC;QAEF,MAAM,OAAO,GAAG,CAAC,KAAU,EAAE,EAAE;YAC7B,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAE7C,MAAM,UAAU,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;YACjD,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;YAEvD,IAAI,iBAAiB,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACvC,MAAM,CACJ,KAAK,EACL,sFAAsF,iBAAiB,CAAC,MAAM,GAAG,CAClH,CAAC;YACJ,CAAC;iBAAM,IAAI,iBAAiB,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC9C,MAAM,CACJ,IAAI,EACJ,SAAS,EACT,sEAAsE,CACvE,CAAC;YACJ,CAAC;iBAAM,IAAI,iBAAiB,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC9C,MAAM,CACJ,KAAK,EACL,yFAAyF,iBAAiB,CACxG,iBAAiB,CAAC,IAAI,CACvB,KAAK,iBAAiB,CAAC,WAAW,GAAG,CACvC,CAAC;YACJ,CAAC;iBAAM,IAAI,iBAAiB,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC/C,MAAM,CACJ,KAAK,EACL,2FAA2F,CAC5F,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,MAAM,gBAAgB,GAAU,iBAAiB,CAAC;YACpD,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAE3E,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACrD,IAAI,CAAC,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAEvD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC"}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import type { Result } from "ethers/abi";
|
2
|
+
/**
|
3
|
+
* Try to obtain the return data of a transaction from the given value.
|
4
|
+
*
|
5
|
+
* If the value is an error but it doesn't have data, we assume it's not related
|
6
|
+
* to a reverted transaction and we re-throw it.
|
7
|
+
*/
|
8
|
+
export declare function getReturnDataFromError(error: any): string;
|
9
|
+
type DecodedReturnData = {
|
10
|
+
kind: "Error";
|
11
|
+
reason: string;
|
12
|
+
} | {
|
13
|
+
kind: "Empty";
|
14
|
+
} | {
|
15
|
+
kind: "Panic";
|
16
|
+
code: bigint;
|
17
|
+
description: string;
|
18
|
+
} | {
|
19
|
+
kind: "Custom";
|
20
|
+
id: string;
|
21
|
+
data: string;
|
22
|
+
};
|
23
|
+
export declare function decodeReturnData(returnData: string): DecodedReturnData;
|
24
|
+
/**
|
25
|
+
* Takes an ethers result object and converts it into a (potentially nested) array.
|
26
|
+
*
|
27
|
+
* For example, given this error:
|
28
|
+
*
|
29
|
+
* struct Point(uint x, uint y)
|
30
|
+
* error MyError(string, Point)
|
31
|
+
*
|
32
|
+
* revert MyError("foo", Point(1, 2))
|
33
|
+
*
|
34
|
+
* The resulting array will be: ["foo", [1n, 2n]]
|
35
|
+
*/
|
36
|
+
export declare function resultToArray(result: Result): any[];
|
37
|
+
export declare function parseBytes32String(v: string): string;
|
38
|
+
export {};
|
39
|
+
//# sourceMappingURL=utils.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/internal/matchers/reverted/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAezC;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,CAwBzD;AAED,KAAK,iBAAiB,GAClB;IACE,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IACE,IAAI,EAAE,OAAO,CAAC;CACf,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB,GACD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEN,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,iBAAiB,CAsDtE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,EAAE,CAQnD;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEpD"}
|
@@ -0,0 +1,108 @@
|
|
1
|
+
import { HardhatError } from "@nomicfoundation/hardhat-errors";
|
2
|
+
import { ensureError } from "@nomicfoundation/hardhat-utils/error";
|
3
|
+
import { AssertionError } from "chai";
|
4
|
+
import { AbiCoder, decodeBytes32String } from "ethers/abi";
|
5
|
+
import { panicErrorCodeToReason } from "./panic.js";
|
6
|
+
// method id of 'Error(string)'
|
7
|
+
const ERROR_STRING_PREFIX = "0x08c379a0";
|
8
|
+
// method id of 'Panic(uint256)'
|
9
|
+
const PANIC_CODE_PREFIX = "0x4e487b71";
|
10
|
+
/**
|
11
|
+
* Try to obtain the return data of a transaction from the given value.
|
12
|
+
*
|
13
|
+
* If the value is an error but it doesn't have data, we assume it's not related
|
14
|
+
* to a reverted transaction and we re-throw it.
|
15
|
+
*/
|
16
|
+
export function getReturnDataFromError(error) {
|
17
|
+
if (!(error instanceof Error)) {
|
18
|
+
// eslint-disable-next-line no-restricted-syntax -- keep the original chai error structure
|
19
|
+
throw new AssertionError("Expected an Error object");
|
20
|
+
}
|
21
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- some properties do not exist in the default Error instance
|
22
|
+
const typedError = error;
|
23
|
+
const errorData = typedError.data ?? typedError.error?.data;
|
24
|
+
if (errorData === undefined) {
|
25
|
+
// eslint-disable-next-line no-restricted-syntax -- re-throw because the error is not related to a reverted transaction
|
26
|
+
throw error;
|
27
|
+
}
|
28
|
+
const returnData = typeof errorData === "string" ? errorData : errorData.data;
|
29
|
+
if (returnData === undefined || typeof returnData !== "string") {
|
30
|
+
// eslint-disable-next-line no-restricted-syntax -- re-throw because the error is not related to a reverted transaction
|
31
|
+
throw error;
|
32
|
+
}
|
33
|
+
return returnData;
|
34
|
+
}
|
35
|
+
export function decodeReturnData(returnData) {
|
36
|
+
const abi = new AbiCoder();
|
37
|
+
if (returnData === "0x") {
|
38
|
+
return { kind: "Empty" };
|
39
|
+
}
|
40
|
+
else if (returnData.startsWith(ERROR_STRING_PREFIX)) {
|
41
|
+
const encodedReason = returnData.slice(ERROR_STRING_PREFIX.length);
|
42
|
+
let reason;
|
43
|
+
try {
|
44
|
+
reason = abi.decode(["string"], `0x${encodedReason}`)[0];
|
45
|
+
}
|
46
|
+
catch (e) {
|
47
|
+
ensureError(e);
|
48
|
+
throw new HardhatError(HardhatError.ERRORS.CHAI_MATCHERS.DECODING_ERROR, {
|
49
|
+
encodedData: encodedReason,
|
50
|
+
type: "string",
|
51
|
+
reason: e.message,
|
52
|
+
});
|
53
|
+
}
|
54
|
+
return {
|
55
|
+
kind: "Error",
|
56
|
+
reason,
|
57
|
+
};
|
58
|
+
}
|
59
|
+
else if (returnData.startsWith(PANIC_CODE_PREFIX)) {
|
60
|
+
const encodedReason = returnData.slice(PANIC_CODE_PREFIX.length);
|
61
|
+
let code;
|
62
|
+
try {
|
63
|
+
code = abi.decode(["uint256"], `0x${encodedReason}`)[0];
|
64
|
+
}
|
65
|
+
catch (e) {
|
66
|
+
ensureError(e);
|
67
|
+
throw new HardhatError(HardhatError.ERRORS.CHAI_MATCHERS.DECODING_ERROR, {
|
68
|
+
encodedData: encodedReason,
|
69
|
+
type: "uint256",
|
70
|
+
reason: e.message,
|
71
|
+
});
|
72
|
+
}
|
73
|
+
const description = panicErrorCodeToReason(code) ?? "unknown panic code";
|
74
|
+
return {
|
75
|
+
kind: "Panic",
|
76
|
+
code,
|
77
|
+
description,
|
78
|
+
};
|
79
|
+
}
|
80
|
+
return {
|
81
|
+
kind: "Custom",
|
82
|
+
id: returnData.slice(0, 10),
|
83
|
+
data: `0x${returnData.slice(10)}`,
|
84
|
+
};
|
85
|
+
}
|
86
|
+
/**
|
87
|
+
* Takes an ethers result object and converts it into a (potentially nested) array.
|
88
|
+
*
|
89
|
+
* For example, given this error:
|
90
|
+
*
|
91
|
+
* struct Point(uint x, uint y)
|
92
|
+
* error MyError(string, Point)
|
93
|
+
*
|
94
|
+
* revert MyError("foo", Point(1, 2))
|
95
|
+
*
|
96
|
+
* The resulting array will be: ["foo", [1n, 2n]]
|
97
|
+
*/
|
98
|
+
export function resultToArray(result) {
|
99
|
+
return result
|
100
|
+
.toArray()
|
101
|
+
.map((x) => typeof x === "object" && x !== null && "toArray" in x
|
102
|
+
? resultToArray(x)
|
103
|
+
: x);
|
104
|
+
}
|
105
|
+
export function parseBytes32String(v) {
|
106
|
+
return decodeBytes32String(v);
|
107
|
+
}
|
108
|
+
//# sourceMappingURL=utils.js.map
|