hardhat 2.22.11 → 2.22.12

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.
Files changed (90) hide show
  1. package/internal/hardhat-network/provider/provider.d.ts +2 -3
  2. package/internal/hardhat-network/provider/provider.d.ts.map +1 -1
  3. package/internal/hardhat-network/provider/provider.js +5 -19
  4. package/internal/hardhat-network/provider/provider.js.map +1 -1
  5. package/internal/hardhat-network/provider/return-data.d.ts +2 -15
  6. package/internal/hardhat-network/provider/return-data.d.ts.map +1 -1
  7. package/internal/hardhat-network/provider/return-data.js +2 -50
  8. package/internal/hardhat-network/provider/return-data.js.map +1 -1
  9. package/internal/hardhat-network/provider/vm/exit.d.ts +2 -20
  10. package/internal/hardhat-network/provider/vm/exit.d.ts.map +1 -1
  11. package/internal/hardhat-network/provider/vm/exit.js +3 -78
  12. package/internal/hardhat-network/provider/vm/exit.js.map +1 -1
  13. package/internal/hardhat-network/stack-traces/compiler-to-model.d.ts +2 -3
  14. package/internal/hardhat-network/stack-traces/compiler-to-model.d.ts.map +1 -1
  15. package/internal/hardhat-network/stack-traces/compiler-to-model.js +2 -351
  16. package/internal/hardhat-network/stack-traces/compiler-to-model.js.map +1 -1
  17. package/internal/hardhat-network/stack-traces/debug.d.ts +2 -7
  18. package/internal/hardhat-network/stack-traces/debug.d.ts.map +1 -1
  19. package/internal/hardhat-network/stack-traces/debug.js +3 -143
  20. package/internal/hardhat-network/stack-traces/debug.js.map +1 -1
  21. package/internal/hardhat-network/stack-traces/library-utils.d.ts +2 -11
  22. package/internal/hardhat-network/stack-traces/library-utils.d.ts.map +1 -1
  23. package/internal/hardhat-network/stack-traces/library-utils.js +3 -61
  24. package/internal/hardhat-network/stack-traces/library-utils.js.map +1 -1
  25. package/internal/hardhat-network/stack-traces/message-trace.d.ts +2 -51
  26. package/internal/hardhat-network/stack-traces/message-trace.d.ts.map +1 -1
  27. package/internal/hardhat-network/stack-traces/message-trace.js +0 -46
  28. package/internal/hardhat-network/stack-traces/message-trace.js.map +1 -1
  29. package/internal/hardhat-network/stack-traces/solidity-errors.d.ts.map +1 -1
  30. package/internal/hardhat-network/stack-traces/solidity-errors.js +58 -53
  31. package/internal/hardhat-network/stack-traces/solidity-errors.js.map +1 -1
  32. package/internal/hardhat-network/stack-traces/solidity-stack-trace.d.ts +4 -155
  33. package/internal/hardhat-network/stack-traces/solidity-stack-trace.d.ts.map +1 -1
  34. package/internal/hardhat-network/stack-traces/solidity-stack-trace.js +12 -37
  35. package/internal/hardhat-network/stack-traces/solidity-stack-trace.js.map +1 -1
  36. package/internal/hardhat-network/stack-traces/solidityTracer.d.ts +2 -13
  37. package/internal/hardhat-network/stack-traces/solidityTracer.d.ts.map +1 -1
  38. package/internal/hardhat-network/stack-traces/solidityTracer.js +2 -162
  39. package/internal/hardhat-network/stack-traces/solidityTracer.js.map +1 -1
  40. package/internal/hardhat-network/stack-traces/vm-trace-decoder.d.ts +4 -15
  41. package/internal/hardhat-network/stack-traces/vm-trace-decoder.d.ts.map +1 -1
  42. package/internal/hardhat-network/stack-traces/vm-trace-decoder.js +6 -70
  43. package/internal/hardhat-network/stack-traces/vm-trace-decoder.js.map +1 -1
  44. package/internal/hardhat-network/stack-traces/vm-tracer.d.ts +2 -19
  45. package/internal/hardhat-network/stack-traces/vm-tracer.d.ts.map +1 -1
  46. package/internal/hardhat-network/stack-traces/vm-tracer.js +3 -150
  47. package/internal/hardhat-network/stack-traces/vm-tracer.js.map +1 -1
  48. package/package.json +4 -4
  49. package/src/internal/hardhat-network/provider/provider.ts +11 -24
  50. package/src/internal/hardhat-network/provider/return-data.ts +5 -73
  51. package/src/internal/hardhat-network/provider/vm/exit.ts +4 -92
  52. package/src/internal/hardhat-network/stack-traces/compiler-to-model.ts +5 -697
  53. package/src/internal/hardhat-network/stack-traces/debug.ts +5 -218
  54. package/src/internal/hardhat-network/stack-traces/library-utils.ts +5 -90
  55. package/src/internal/hardhat-network/stack-traces/message-trace.ts +5 -122
  56. package/src/internal/hardhat-network/stack-traces/solidity-errors.ts +16 -15
  57. package/src/internal/hardhat-network/stack-traces/solidity-stack-trace.ts +83 -186
  58. package/src/internal/hardhat-network/stack-traces/solidityTracer.ts +5 -253
  59. package/src/internal/hardhat-network/stack-traces/vm-trace-decoder.ts +15 -108
  60. package/src/internal/hardhat-network/stack-traces/vm-tracer.ts +5 -206
  61. package/internal/hardhat-network/stack-traces/contracts-identifier.d.ts +0 -15
  62. package/internal/hardhat-network/stack-traces/contracts-identifier.d.ts.map +0 -1
  63. package/internal/hardhat-network/stack-traces/contracts-identifier.js +0 -166
  64. package/internal/hardhat-network/stack-traces/contracts-identifier.js.map +0 -1
  65. package/internal/hardhat-network/stack-traces/error-inferrer.d.ts +0 -85
  66. package/internal/hardhat-network/stack-traces/error-inferrer.d.ts.map +0 -1
  67. package/internal/hardhat-network/stack-traces/error-inferrer.js +0 -1168
  68. package/internal/hardhat-network/stack-traces/error-inferrer.js.map +0 -1
  69. package/internal/hardhat-network/stack-traces/mapped-inlined-internal-functions-heuristics.d.ts +0 -24
  70. package/internal/hardhat-network/stack-traces/mapped-inlined-internal-functions-heuristics.d.ts.map +0 -1
  71. package/internal/hardhat-network/stack-traces/mapped-inlined-internal-functions-heuristics.js +0 -116
  72. package/internal/hardhat-network/stack-traces/mapped-inlined-internal-functions-heuristics.js.map +0 -1
  73. package/internal/hardhat-network/stack-traces/model.d.ts +0 -140
  74. package/internal/hardhat-network/stack-traces/model.d.ts.map +0 -1
  75. package/internal/hardhat-network/stack-traces/model.js +0 -328
  76. package/internal/hardhat-network/stack-traces/model.js.map +0 -1
  77. package/internal/hardhat-network/stack-traces/opcodes.d.ts +0 -266
  78. package/internal/hardhat-network/stack-traces/opcodes.d.ts.map +0 -1
  79. package/internal/hardhat-network/stack-traces/opcodes.js +0 -320
  80. package/internal/hardhat-network/stack-traces/opcodes.js.map +0 -1
  81. package/internal/hardhat-network/stack-traces/source-maps.d.ts +0 -13
  82. package/internal/hardhat-network/stack-traces/source-maps.d.ts.map +0 -1
  83. package/internal/hardhat-network/stack-traces/source-maps.js +0 -106
  84. package/internal/hardhat-network/stack-traces/source-maps.js.map +0 -1
  85. package/src/internal/hardhat-network/stack-traces/contracts-identifier.ts +0 -235
  86. package/src/internal/hardhat-network/stack-traces/error-inferrer.ts +0 -1845
  87. package/src/internal/hardhat-network/stack-traces/mapped-inlined-internal-functions-heuristics.ts +0 -163
  88. package/src/internal/hardhat-network/stack-traces/model.ts +0 -409
  89. package/src/internal/hardhat-network/stack-traces/opcodes.ts +0 -344
  90. package/src/internal/hardhat-network/stack-traces/source-maps.ts +0 -167
@@ -1,1168 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.instructionToCallstackStackTraceEntry = exports.ErrorInferrer = void 0;
7
- /* eslint "@typescript-eslint/no-non-null-assertion": "error" */
8
- const abi_1 = require("@ethersproject/abi");
9
- const ethereumjs_util_1 = require("@nomicfoundation/ethereumjs-util");
10
- const semver_1 = __importDefault(require("semver"));
11
- const errors_1 = require("../../core/errors");
12
- const abi_helpers_1 = require("../../util/abi-helpers");
13
- const return_data_1 = require("../provider/return-data");
14
- const exit_1 = require("../provider/vm/exit");
15
- const message_trace_1 = require("./message-trace");
16
- const model_1 = require("./model");
17
- const opcodes_1 = require("./opcodes");
18
- const solidity_stack_trace_1 = require("./solidity-stack-trace");
19
- const FIRST_SOLC_VERSION_CREATE_PARAMS_VALIDATION = "0.5.9";
20
- const FIRST_SOLC_VERSION_RECEIVE_FUNCTION = "0.6.0";
21
- const FIRST_SOLC_VERSION_WITH_UNMAPPED_REVERTS = "0.6.3";
22
- /* eslint-disable @nomicfoundation/hardhat-internal-rules/only-hardhat-error */
23
- class ErrorInferrer {
24
- inferBeforeTracingCallMessage(trace) {
25
- if (this._isDirectLibraryCall(trace)) {
26
- return this._getDirectLibraryCallErrorStackTrace(trace);
27
- }
28
- const calledFunction = trace.bytecode.contract.getFunctionFromSelector(trace.calldata.slice(0, 4));
29
- if (calledFunction !== undefined &&
30
- this._isFunctionNotPayableError(trace, calledFunction)) {
31
- return [
32
- {
33
- type: solidity_stack_trace_1.StackTraceEntryType.FUNCTION_NOT_PAYABLE_ERROR,
34
- sourceReference: this._getFunctionStartSourceReference(trace, calledFunction),
35
- value: trace.value,
36
- },
37
- ];
38
- }
39
- if (this._isMissingFunctionAndFallbackError(trace, calledFunction)) {
40
- if (this._emptyCalldataAndNoReceive(trace)) {
41
- return [
42
- {
43
- type: solidity_stack_trace_1.StackTraceEntryType.MISSING_FALLBACK_OR_RECEIVE_ERROR,
44
- sourceReference: this._getContractStartWithoutFunctionSourceReference(trace),
45
- },
46
- ];
47
- }
48
- return [
49
- {
50
- type: solidity_stack_trace_1.StackTraceEntryType.UNRECOGNIZED_FUNCTION_WITHOUT_FALLBACK_ERROR,
51
- sourceReference: this._getContractStartWithoutFunctionSourceReference(trace),
52
- },
53
- ];
54
- }
55
- if (this._isFallbackNotPayableError(trace, calledFunction)) {
56
- if (this._emptyCalldataAndNoReceive(trace)) {
57
- return [
58
- {
59
- type: solidity_stack_trace_1.StackTraceEntryType.FALLBACK_NOT_PAYABLE_AND_NO_RECEIVE_ERROR,
60
- sourceReference: this._getFallbackStartSourceReference(trace),
61
- value: trace.value,
62
- },
63
- ];
64
- }
65
- return [
66
- {
67
- type: solidity_stack_trace_1.StackTraceEntryType.FALLBACK_NOT_PAYABLE_ERROR,
68
- sourceReference: this._getFallbackStartSourceReference(trace),
69
- value: trace.value,
70
- },
71
- ];
72
- }
73
- }
74
- inferBeforeTracingCreateMessage(trace) {
75
- if (this._isConstructorNotPayableError(trace)) {
76
- return [
77
- {
78
- type: solidity_stack_trace_1.StackTraceEntryType.FUNCTION_NOT_PAYABLE_ERROR,
79
- sourceReference: this._getConstructorStartSourceReference(trace),
80
- value: trace.value,
81
- },
82
- ];
83
- }
84
- if (this._isConstructorInvalidArgumentsError(trace)) {
85
- return [
86
- {
87
- type: solidity_stack_trace_1.StackTraceEntryType.INVALID_PARAMS_ERROR,
88
- sourceReference: this._getConstructorStartSourceReference(trace),
89
- },
90
- ];
91
- }
92
- }
93
- inferAfterTracing(trace, stacktrace, functionJumpdests, jumpedIntoFunction, lastSubmessageData) {
94
- return (this._checkLastSubmessage(trace, stacktrace, lastSubmessageData) ??
95
- this._checkFailedLastCall(trace, stacktrace) ??
96
- this._checkLastInstruction(trace, stacktrace, functionJumpdests, jumpedIntoFunction) ??
97
- this._checkNonContractCalled(trace, stacktrace) ??
98
- this._checkSolidity063UnmappedRevert(trace, stacktrace) ??
99
- this._checkContractTooLarge(trace) ??
100
- this._otherExecutionErrorStacktrace(trace, stacktrace));
101
- }
102
- filterRedundantFrames(stacktrace) {
103
- return stacktrace.filter((frame, i) => {
104
- if (i + 1 === stacktrace.length) {
105
- return true;
106
- }
107
- const nextFrame = stacktrace[i + 1];
108
- // we can only filter frames if we know their sourceReference
109
- // and the one from the next frame
110
- if (frame.sourceReference === undefined ||
111
- nextFrame.sourceReference === undefined) {
112
- return true;
113
- }
114
- // look TWO frames ahead to determine if this is a specific occurrence of
115
- // a redundant CALLSTACK_ENTRY frame observed when using Solidity 0.8.5:
116
- if (frame.type === solidity_stack_trace_1.StackTraceEntryType.CALLSTACK_ENTRY &&
117
- i + 2 < stacktrace.length &&
118
- stacktrace[i + 2].sourceReference !== undefined &&
119
- stacktrace[i + 2].type === solidity_stack_trace_1.StackTraceEntryType.RETURNDATA_SIZE_ERROR) {
120
- // ! below for tsc. we confirmed existence in the enclosing conditional.
121
- const thatSrcRef = stacktrace[i + 2].sourceReference;
122
- if (thatSrcRef !== undefined &&
123
- frame.sourceReference.range[0] === thatSrcRef.range[0] &&
124
- frame.sourceReference.range[1] === thatSrcRef.range[1] &&
125
- frame.sourceReference.line === thatSrcRef.line) {
126
- return false;
127
- }
128
- }
129
- // constructors contain the whole contract, so we ignore them
130
- if (frame.sourceReference.function === "constructor" &&
131
- nextFrame.sourceReference.function !== "constructor") {
132
- return true;
133
- }
134
- // this is probably a recursive call
135
- if (i > 0 &&
136
- frame.type === nextFrame.type &&
137
- frame.sourceReference.range[0] === nextFrame.sourceReference.range[0] &&
138
- frame.sourceReference.range[1] === nextFrame.sourceReference.range[1] &&
139
- frame.sourceReference.line === nextFrame.sourceReference.line) {
140
- return true;
141
- }
142
- if (frame.sourceReference.range[0] <= nextFrame.sourceReference.range[0] &&
143
- frame.sourceReference.range[1] >= nextFrame.sourceReference.range[1]) {
144
- return false;
145
- }
146
- return true;
147
- });
148
- }
149
- // Heuristics
150
- /**
151
- * Check if the last submessage can be used to generate the stack trace.
152
- */
153
- _checkLastSubmessage(trace, stacktrace, lastSubmessageData) {
154
- if (lastSubmessageData === undefined) {
155
- return undefined;
156
- }
157
- const inferredStacktrace = [...stacktrace];
158
- // get the instruction before the submessage and add it to the stack trace
159
- const callStep = trace.steps[lastSubmessageData.stepIndex - 1];
160
- if (!(0, message_trace_1.isEvmStep)(callStep)) {
161
- throw new Error("This should not happen: MessageTrace should be preceded by a EVM step");
162
- }
163
- const callInst = trace.bytecode.getInstruction(callStep.pc);
164
- const callStackFrame = instructionToCallstackStackTraceEntry(trace.bytecode, callInst);
165
- const lastMessageFailed = lastSubmessageData.messageTrace.exit.isError();
166
- if (lastMessageFailed) {
167
- // add the call/create that generated the message to the stack trace
168
- inferredStacktrace.push(callStackFrame);
169
- if (this._isSubtraceErrorPropagated(trace, lastSubmessageData.stepIndex) ||
170
- this._isProxyErrorPropagated(trace, lastSubmessageData.stepIndex)) {
171
- inferredStacktrace.push(...lastSubmessageData.stacktrace);
172
- if (this._isContractCallRunOutOfGasError(trace, lastSubmessageData.stepIndex)) {
173
- const lastFrame = inferredStacktrace.pop();
174
- (0, errors_1.assertHardhatInvariant)(lastFrame !== undefined, "Expected inferred stack trace to have at least one frame");
175
- inferredStacktrace.push({
176
- type: solidity_stack_trace_1.StackTraceEntryType.CONTRACT_CALL_RUN_OUT_OF_GAS_ERROR,
177
- sourceReference: lastFrame.sourceReference,
178
- });
179
- }
180
- return this._fixInitialModifier(trace, inferredStacktrace);
181
- }
182
- }
183
- else {
184
- const isReturnDataSizeError = this._failsRightAfterCall(trace, lastSubmessageData.stepIndex);
185
- if (isReturnDataSizeError) {
186
- inferredStacktrace.push({
187
- type: solidity_stack_trace_1.StackTraceEntryType.RETURNDATA_SIZE_ERROR,
188
- sourceReference: callStackFrame.sourceReference,
189
- });
190
- return this._fixInitialModifier(trace, inferredStacktrace);
191
- }
192
- }
193
- }
194
- /**
195
- * Check if the last call/create that was done failed.
196
- */
197
- _checkFailedLastCall(trace, stacktrace) {
198
- for (let stepIndex = trace.steps.length - 2; stepIndex >= 0; stepIndex--) {
199
- const step = trace.steps[stepIndex];
200
- const nextStep = trace.steps[stepIndex + 1];
201
- if (!(0, message_trace_1.isEvmStep)(step)) {
202
- return;
203
- }
204
- const inst = trace.bytecode.getInstruction(step.pc);
205
- const isCallOrCreate = (0, opcodes_1.isCall)(inst.opcode) || (0, opcodes_1.isCreate)(inst.opcode);
206
- if (isCallOrCreate && (0, message_trace_1.isEvmStep)(nextStep)) {
207
- if (this._isCallFailedError(trace, stepIndex, inst)) {
208
- const inferredStacktrace = [
209
- ...stacktrace,
210
- this._callInstructionToCallFailedToExecuteStackTraceEntry(trace.bytecode, inst),
211
- ];
212
- return this._fixInitialModifier(trace, inferredStacktrace);
213
- }
214
- }
215
- }
216
- }
217
- /**
218
- * Check if the execution stopped with a revert or an invalid opcode.
219
- */
220
- _checkRevertOrInvalidOpcode(trace, stacktrace, lastInstruction, functionJumpdests, jumpedIntoFunction) {
221
- if (lastInstruction.opcode !== opcodes_1.Opcode.REVERT &&
222
- lastInstruction.opcode !== opcodes_1.Opcode.INVALID) {
223
- return;
224
- }
225
- const inferredStacktrace = [...stacktrace];
226
- if (lastInstruction.location !== undefined &&
227
- (!(0, message_trace_1.isDecodedCallTrace)(trace) || jumpedIntoFunction)) {
228
- // There should always be a function here, but that's not the case with optimizations.
229
- //
230
- // If this is a create trace, we already checked args and nonpayable failures before
231
- // calling this function.
232
- //
233
- // If it's a call trace, we already jumped into a function. But optimizations can happen.
234
- const failingFunction = lastInstruction.location.getContainingFunction();
235
- // If the failure is in a modifier we add an entry with the function/constructor
236
- if (failingFunction !== undefined &&
237
- failingFunction.type === model_1.ContractFunctionType.MODIFIER) {
238
- inferredStacktrace.push(this._getEntryBeforeFailureInModifier(trace, functionJumpdests));
239
- }
240
- }
241
- const panicStacktrace = this._checkPanic(trace, inferredStacktrace, lastInstruction);
242
- if (panicStacktrace !== undefined) {
243
- return panicStacktrace;
244
- }
245
- const customErrorStacktrace = this._checkCustomErrors(trace, inferredStacktrace, lastInstruction);
246
- if (customErrorStacktrace !== undefined) {
247
- return customErrorStacktrace;
248
- }
249
- if (lastInstruction.location !== undefined &&
250
- (!(0, message_trace_1.isDecodedCallTrace)(trace) || jumpedIntoFunction)) {
251
- const failingFunction = lastInstruction.location.getContainingFunction();
252
- if (failingFunction !== undefined) {
253
- inferredStacktrace.push(this._instructionWithinFunctionToRevertStackTraceEntry(trace, lastInstruction));
254
- }
255
- else if ((0, message_trace_1.isDecodedCallTrace)(trace)) {
256
- // This is here because of the optimizations
257
- const functionSelector = trace.bytecode.contract.getFunctionFromSelector(trace.calldata.slice(0, 4));
258
- // in general this shouldn't happen, but it does when viaIR is enabled,
259
- // "optimizerSteps": "u" is used, and the called function is fallback or
260
- // receive
261
- if (functionSelector === undefined) {
262
- return;
263
- }
264
- inferredStacktrace.push({
265
- type: solidity_stack_trace_1.StackTraceEntryType.REVERT_ERROR,
266
- sourceReference: this._getFunctionStartSourceReference(trace, functionSelector),
267
- message: new return_data_1.ReturnData(trace.returnData),
268
- isInvalidOpcodeError: lastInstruction.opcode === opcodes_1.Opcode.INVALID,
269
- });
270
- }
271
- else {
272
- // This is here because of the optimizations
273
- inferredStacktrace.push({
274
- type: solidity_stack_trace_1.StackTraceEntryType.REVERT_ERROR,
275
- sourceReference: this._getConstructorStartSourceReference(trace),
276
- message: new return_data_1.ReturnData(trace.returnData),
277
- isInvalidOpcodeError: lastInstruction.opcode === opcodes_1.Opcode.INVALID,
278
- });
279
- }
280
- return this._fixInitialModifier(trace, inferredStacktrace);
281
- }
282
- // If the revert instruction is not mapped but there is return data,
283
- // we add the frame anyway, sith the best sourceReference we can get
284
- if (lastInstruction.location === undefined && trace.returnData.length > 0) {
285
- const revertFrame = {
286
- type: solidity_stack_trace_1.StackTraceEntryType.REVERT_ERROR,
287
- sourceReference: this._getLastSourceReference(trace) ??
288
- this._getContractStartWithoutFunctionSourceReference(trace),
289
- message: new return_data_1.ReturnData(trace.returnData),
290
- isInvalidOpcodeError: lastInstruction.opcode === opcodes_1.Opcode.INVALID,
291
- };
292
- inferredStacktrace.push(revertFrame);
293
- return this._fixInitialModifier(trace, inferredStacktrace);
294
- }
295
- }
296
- /**
297
- * Check if the trace reverted with a panic error.
298
- */
299
- _checkPanic(trace, stacktrace, lastInstruction) {
300
- if (!this._isPanicReturnData(trace.returnData)) {
301
- return;
302
- }
303
- // If the last frame is an internal function, it means that the trace
304
- // jumped there to return the panic. If that's the case, we remove that
305
- // frame.
306
- const lastFrame = stacktrace[stacktrace.length - 1];
307
- if (lastFrame?.type === solidity_stack_trace_1.StackTraceEntryType.INTERNAL_FUNCTION_CALLSTACK_ENTRY) {
308
- stacktrace.splice(-1);
309
- }
310
- const panicReturnData = new return_data_1.ReturnData(trace.returnData);
311
- const errorCode = panicReturnData.decodePanic();
312
- // if the error comes from a call to a zero-initialized function,
313
- // we remove the last frame, which represents the call, to avoid
314
- // having duplicated frames
315
- if (errorCode === 0x51n) {
316
- stacktrace.splice(-1);
317
- }
318
- const inferredStacktrace = [...stacktrace];
319
- inferredStacktrace.push(this._instructionWithinFunctionToPanicStackTraceEntry(trace, lastInstruction, errorCode));
320
- return this._fixInitialModifier(trace, inferredStacktrace);
321
- }
322
- _checkCustomErrors(trace, stacktrace, lastInstruction) {
323
- const returnData = new return_data_1.ReturnData(trace.returnData);
324
- if (returnData.isEmpty() || returnData.isErrorReturnData()) {
325
- // if there is no return data, or if it's a Error(string),
326
- // then it can't be a custom error
327
- return;
328
- }
329
- const rawReturnData = Buffer.from(returnData.value).toString("hex");
330
- let errorMessage = `reverted with an unrecognized custom error (return data: 0x${rawReturnData})`;
331
- for (const customError of trace.bytecode.contract.customErrors) {
332
- if (returnData.matchesSelector(customError.selector)) {
333
- // if the return data matches a custom error in the called contract,
334
- // we format the message using the returnData and the custom error instance
335
- const decodedValues = abi_1.defaultAbiCoder.decode(customError.paramTypes, returnData.value.slice(4));
336
- const params = abi_helpers_1.AbiHelpers.formatValues([...decodedValues]);
337
- errorMessage = `reverted with custom error '${customError.name}(${params})'`;
338
- break;
339
- }
340
- }
341
- const inferredStacktrace = [...stacktrace];
342
- inferredStacktrace.push(this._instructionWithinFunctionToCustomErrorStackTraceEntry(trace, lastInstruction, errorMessage));
343
- return this._fixInitialModifier(trace, inferredStacktrace);
344
- }
345
- /**
346
- * Check last instruction to try to infer the error.
347
- */
348
- _checkLastInstruction(trace, stacktrace, functionJumpdests, jumpedIntoFunction) {
349
- if (trace.steps.length === 0) {
350
- return;
351
- }
352
- const lastStep = trace.steps[trace.steps.length - 1];
353
- if (!(0, message_trace_1.isEvmStep)(lastStep)) {
354
- throw new Error("This should not happen: MessageTrace ends with a subtrace");
355
- }
356
- const lastInstruction = trace.bytecode.getInstruction(lastStep.pc);
357
- const revertOrInvalidStacktrace = this._checkRevertOrInvalidOpcode(trace, stacktrace, lastInstruction, functionJumpdests, jumpedIntoFunction);
358
- if (revertOrInvalidStacktrace !== undefined) {
359
- return revertOrInvalidStacktrace;
360
- }
361
- if ((0, message_trace_1.isDecodedCallTrace)(trace) && !jumpedIntoFunction) {
362
- if (this._hasFailedInsideTheFallbackFunction(trace) ||
363
- this._hasFailedInsideTheReceiveFunction(trace)) {
364
- return [
365
- this._instructionWithinFunctionToRevertStackTraceEntry(trace, lastInstruction),
366
- ];
367
- }
368
- // Sometimes we do fail inside of a function but there's no jump into
369
- if (lastInstruction.location !== undefined) {
370
- const failingFunction = lastInstruction.location.getContainingFunction();
371
- if (failingFunction !== undefined) {
372
- return [
373
- {
374
- type: solidity_stack_trace_1.StackTraceEntryType.REVERT_ERROR,
375
- sourceReference: this._getFunctionStartSourceReference(trace, failingFunction),
376
- message: new return_data_1.ReturnData(trace.returnData),
377
- isInvalidOpcodeError: lastInstruction.opcode === opcodes_1.Opcode.INVALID,
378
- },
379
- ];
380
- }
381
- }
382
- const calledFunction = trace.bytecode.contract.getFunctionFromSelector(trace.calldata.slice(0, 4));
383
- if (calledFunction !== undefined) {
384
- const isValidCalldata = calledFunction.isValidCalldata(trace.calldata.slice(4));
385
- if (!isValidCalldata) {
386
- return [
387
- {
388
- type: solidity_stack_trace_1.StackTraceEntryType.INVALID_PARAMS_ERROR,
389
- sourceReference: this._getFunctionStartSourceReference(trace, calledFunction),
390
- },
391
- ];
392
- }
393
- }
394
- if (this._solidity063MaybeUnmappedRevert(trace)) {
395
- const revertFrame = this._solidity063GetFrameForUnmappedRevertBeforeFunction(trace);
396
- if (revertFrame !== undefined) {
397
- return [revertFrame];
398
- }
399
- }
400
- return [this._getOtherErrorBeforeCalledFunctionStackTraceEntry(trace)];
401
- }
402
- }
403
- _checkNonContractCalled(trace, stacktrace) {
404
- if (this._isCalledNonContractAccountError(trace)) {
405
- const sourceReference = this._getLastSourceReference(trace);
406
- // We are sure this is not undefined because there was at least a call instruction
407
- (0, errors_1.assertHardhatInvariant)(sourceReference !== undefined, "Expected source reference to be defined");
408
- const nonContractCalledFrame = {
409
- type: solidity_stack_trace_1.StackTraceEntryType.NONCONTRACT_ACCOUNT_CALLED_ERROR,
410
- sourceReference,
411
- };
412
- return [...stacktrace, nonContractCalledFrame];
413
- }
414
- }
415
- _checkSolidity063UnmappedRevert(trace, stacktrace) {
416
- if (this._solidity063MaybeUnmappedRevert(trace)) {
417
- const revertFrame = this._solidity063GetFrameForUnmappedRevertWithinFunction(trace);
418
- if (revertFrame !== undefined) {
419
- return [...stacktrace, revertFrame];
420
- }
421
- }
422
- }
423
- _checkContractTooLarge(trace) {
424
- if ((0, message_trace_1.isCreateTrace)(trace) && this._isContractTooLargeError(trace)) {
425
- return [
426
- {
427
- type: solidity_stack_trace_1.StackTraceEntryType.CONTRACT_TOO_LARGE_ERROR,
428
- sourceReference: this._getConstructorStartSourceReference(trace),
429
- },
430
- ];
431
- }
432
- }
433
- _otherExecutionErrorStacktrace(trace, stacktrace) {
434
- const otherExecutionErrorFrame = {
435
- type: solidity_stack_trace_1.StackTraceEntryType.OTHER_EXECUTION_ERROR,
436
- sourceReference: this._getLastSourceReference(trace),
437
- };
438
- return [...stacktrace, otherExecutionErrorFrame];
439
- }
440
- // Helpers
441
- _fixInitialModifier(trace, stacktrace) {
442
- const firstEntry = stacktrace[0];
443
- if (firstEntry !== undefined &&
444
- firstEntry.type === solidity_stack_trace_1.StackTraceEntryType.CALLSTACK_ENTRY &&
445
- firstEntry.functionType === model_1.ContractFunctionType.MODIFIER) {
446
- return [
447
- this._getEntryBeforeInitialModifierCallstackEntry(trace),
448
- ...stacktrace,
449
- ];
450
- }
451
- return stacktrace;
452
- }
453
- _isDirectLibraryCall(trace) {
454
- return (trace.depth === 0 && trace.bytecode.contract.type === model_1.ContractType.LIBRARY);
455
- }
456
- _getDirectLibraryCallErrorStackTrace(trace) {
457
- const func = trace.bytecode.contract.getFunctionFromSelector(trace.calldata.slice(0, 4));
458
- if (func !== undefined) {
459
- return [
460
- {
461
- type: solidity_stack_trace_1.StackTraceEntryType.DIRECT_LIBRARY_CALL_ERROR,
462
- sourceReference: this._getFunctionStartSourceReference(trace, func),
463
- },
464
- ];
465
- }
466
- return [
467
- {
468
- type: solidity_stack_trace_1.StackTraceEntryType.DIRECT_LIBRARY_CALL_ERROR,
469
- sourceReference: this._getContractStartWithoutFunctionSourceReference(trace),
470
- },
471
- ];
472
- }
473
- _isFunctionNotPayableError(trace, calledFunction) {
474
- // This error doesn't return data
475
- if (trace.returnData.length > 0) {
476
- return false;
477
- }
478
- if (trace.value <= 0n) {
479
- return false;
480
- }
481
- // Libraries don't have a nonpayable check
482
- if (trace.bytecode.contract.type === model_1.ContractType.LIBRARY) {
483
- return false;
484
- }
485
- return calledFunction.isPayable === undefined || !calledFunction.isPayable;
486
- }
487
- _getFunctionStartSourceReference(trace, func) {
488
- return {
489
- sourceName: func.location.file.sourceName,
490
- sourceContent: func.location.file.content,
491
- contract: trace.bytecode.contract.name,
492
- function: func.name,
493
- line: func.location.getStartingLineNumber(),
494
- range: [
495
- func.location.offset,
496
- func.location.offset + func.location.length,
497
- ],
498
- };
499
- }
500
- _isMissingFunctionAndFallbackError(trace, calledFunction) {
501
- // This error doesn't return data
502
- if (trace.returnData.length > 0) {
503
- return false;
504
- }
505
- // the called function exists in the contract
506
- if (calledFunction !== undefined) {
507
- return false;
508
- }
509
- // there's a receive function and no calldata
510
- if (trace.calldata.length === 0 &&
511
- trace.bytecode.contract.receive !== undefined) {
512
- return false;
513
- }
514
- return trace.bytecode.contract.fallback === undefined;
515
- }
516
- _emptyCalldataAndNoReceive(trace) {
517
- // this only makes sense when receive functions are available
518
- if (semver_1.default.lt(trace.bytecode.compilerVersion, FIRST_SOLC_VERSION_RECEIVE_FUNCTION)) {
519
- return false;
520
- }
521
- return (trace.calldata.length === 0 &&
522
- trace.bytecode.contract.receive === undefined);
523
- }
524
- _getContractStartWithoutFunctionSourceReference(trace) {
525
- const location = trace.bytecode.contract.location;
526
- return {
527
- sourceName: location.file.sourceName,
528
- sourceContent: location.file.content,
529
- contract: trace.bytecode.contract.name,
530
- line: location.getStartingLineNumber(),
531
- range: [location.offset, location.offset + location.length],
532
- };
533
- }
534
- _isFallbackNotPayableError(trace, calledFunction) {
535
- if (calledFunction !== undefined) {
536
- return false;
537
- }
538
- // This error doesn't return data
539
- if (trace.returnData.length > 0) {
540
- return false;
541
- }
542
- if (trace.value <= 0n) {
543
- return false;
544
- }
545
- if (trace.bytecode.contract.fallback === undefined) {
546
- return false;
547
- }
548
- const isPayable = trace.bytecode.contract.fallback.isPayable;
549
- return isPayable === undefined || !isPayable;
550
- }
551
- _getFallbackStartSourceReference(trace) {
552
- const func = trace.bytecode.contract.fallback;
553
- if (func === undefined) {
554
- throw new Error("This shouldn't happen: trying to get fallback source reference from a contract without fallback");
555
- }
556
- return {
557
- sourceName: func.location.file.sourceName,
558
- sourceContent: func.location.file.content,
559
- contract: trace.bytecode.contract.name,
560
- function: solidity_stack_trace_1.FALLBACK_FUNCTION_NAME,
561
- line: func.location.getStartingLineNumber(),
562
- range: [
563
- func.location.offset,
564
- func.location.offset + func.location.length,
565
- ],
566
- };
567
- }
568
- _isConstructorNotPayableError(trace) {
569
- // This error doesn't return data
570
- if (trace.returnData.length > 0) {
571
- return false;
572
- }
573
- const constructor = trace.bytecode.contract.constructorFunction;
574
- // This function is only matters with contracts that have constructors defined. The ones that
575
- // don't are abstract contracts, or their constructor doesn't take any argument.
576
- if (constructor === undefined) {
577
- return false;
578
- }
579
- return (trace.value > 0n &&
580
- (constructor.isPayable === undefined || !constructor.isPayable));
581
- }
582
- /**
583
- * Returns a source reference pointing to the constructor if it exists, or to the contract
584
- * otherwise.
585
- */
586
- _getConstructorStartSourceReference(trace) {
587
- const contract = trace.bytecode.contract;
588
- const constructor = contract.constructorFunction;
589
- const line = constructor !== undefined
590
- ? constructor.location.getStartingLineNumber()
591
- : contract.location.getStartingLineNumber();
592
- return {
593
- sourceName: contract.location.file.sourceName,
594
- sourceContent: contract.location.file.content,
595
- contract: contract.name,
596
- function: solidity_stack_trace_1.CONSTRUCTOR_FUNCTION_NAME,
597
- line,
598
- range: [
599
- contract.location.offset,
600
- contract.location.offset + contract.location.length,
601
- ],
602
- };
603
- }
604
- _isConstructorInvalidArgumentsError(trace) {
605
- // This error doesn't return data
606
- if (trace.returnData.length > 0) {
607
- return false;
608
- }
609
- const contract = trace.bytecode.contract;
610
- const constructor = contract.constructorFunction;
611
- // This function is only matters with contracts that have constructors defined. The ones that
612
- // don't are abstract contracts, or their constructor doesn't take any argument.
613
- if (constructor === undefined) {
614
- return false;
615
- }
616
- if (semver_1.default.lt(trace.bytecode.compilerVersion, FIRST_SOLC_VERSION_CREATE_PARAMS_VALIDATION)) {
617
- return false;
618
- }
619
- const lastStep = trace.steps[trace.steps.length - 1];
620
- if (!(0, message_trace_1.isEvmStep)(lastStep)) {
621
- return false;
622
- }
623
- const lastInst = trace.bytecode.getInstruction(lastStep.pc);
624
- if (lastInst.opcode !== opcodes_1.Opcode.REVERT || lastInst.location !== undefined) {
625
- return false;
626
- }
627
- let hasReadDeploymentCodeSize = false;
628
- // eslint-disable-next-line @typescript-eslint/prefer-for-of
629
- for (let stepIndex = 0; stepIndex < trace.steps.length; stepIndex++) {
630
- const step = trace.steps[stepIndex];
631
- if (!(0, message_trace_1.isEvmStep)(step)) {
632
- return false;
633
- }
634
- const inst = trace.bytecode.getInstruction(step.pc);
635
- if (inst.location !== undefined &&
636
- !contract.location.equals(inst.location) &&
637
- !constructor.location.equals(inst.location)) {
638
- return false;
639
- }
640
- if (inst.opcode === opcodes_1.Opcode.CODESIZE && (0, message_trace_1.isCreateTrace)(trace)) {
641
- hasReadDeploymentCodeSize = true;
642
- }
643
- }
644
- return hasReadDeploymentCodeSize;
645
- }
646
- _getEntryBeforeInitialModifierCallstackEntry(trace) {
647
- if ((0, message_trace_1.isDecodedCreateTrace)(trace)) {
648
- return {
649
- type: solidity_stack_trace_1.StackTraceEntryType.CALLSTACK_ENTRY,
650
- sourceReference: this._getConstructorStartSourceReference(trace),
651
- functionType: model_1.ContractFunctionType.CONSTRUCTOR,
652
- };
653
- }
654
- const calledFunction = trace.bytecode.contract.getFunctionFromSelector(trace.calldata.slice(0, 4));
655
- if (calledFunction !== undefined) {
656
- return {
657
- type: solidity_stack_trace_1.StackTraceEntryType.CALLSTACK_ENTRY,
658
- sourceReference: this._getFunctionStartSourceReference(trace, calledFunction),
659
- functionType: model_1.ContractFunctionType.FUNCTION,
660
- };
661
- }
662
- // If it failed or made a call from within a modifier, and the selector doesn't match
663
- // any function, it must have a fallback.
664
- return {
665
- type: solidity_stack_trace_1.StackTraceEntryType.CALLSTACK_ENTRY,
666
- sourceReference: this._getFallbackStartSourceReference(trace),
667
- functionType: model_1.ContractFunctionType.FALLBACK,
668
- };
669
- }
670
- _getLastSourceReference(trace) {
671
- for (let i = trace.steps.length - 1; i >= 0; i--) {
672
- const step = trace.steps[i];
673
- if (!(0, message_trace_1.isEvmStep)(step)) {
674
- continue;
675
- }
676
- const inst = trace.bytecode.getInstruction(step.pc);
677
- if (inst.location === undefined) {
678
- continue;
679
- }
680
- const sourceReference = sourceLocationToSourceReference(trace.bytecode, inst.location);
681
- if (sourceReference !== undefined) {
682
- return sourceReference;
683
- }
684
- }
685
- return undefined;
686
- }
687
- _hasFailedInsideTheFallbackFunction(trace) {
688
- const contract = trace.bytecode.contract;
689
- if (contract.fallback === undefined) {
690
- return false;
691
- }
692
- return this._hasFailedInsideFunction(trace, contract.fallback);
693
- }
694
- _hasFailedInsideTheReceiveFunction(trace) {
695
- const contract = trace.bytecode.contract;
696
- if (contract.receive === undefined) {
697
- return false;
698
- }
699
- return this._hasFailedInsideFunction(trace, contract.receive);
700
- }
701
- _hasFailedInsideFunction(trace, func) {
702
- const lastStep = trace.steps[trace.steps.length - 1];
703
- const lastInstruction = trace.bytecode.getInstruction(lastStep.pc);
704
- return (lastInstruction.location !== undefined &&
705
- lastInstruction.opcode === opcodes_1.Opcode.REVERT &&
706
- func.location.contains(lastInstruction.location));
707
- }
708
- _instructionWithinFunctionToRevertStackTraceEntry(trace, inst) {
709
- const sourceReference = sourceLocationToSourceReference(trace.bytecode, inst.location);
710
- (0, errors_1.assertHardhatInvariant)(sourceReference !== undefined, "Expected source reference to be defined");
711
- return {
712
- type: solidity_stack_trace_1.StackTraceEntryType.REVERT_ERROR,
713
- sourceReference,
714
- message: new return_data_1.ReturnData(trace.returnData),
715
- isInvalidOpcodeError: inst.opcode === opcodes_1.Opcode.INVALID,
716
- };
717
- }
718
- _instructionWithinFunctionToUnmappedSolc063RevertErrorStackTraceEntry(trace, inst) {
719
- const sourceReference = sourceLocationToSourceReference(trace.bytecode, inst.location);
720
- return {
721
- type: solidity_stack_trace_1.StackTraceEntryType.UNMAPPED_SOLC_0_6_3_REVERT_ERROR,
722
- sourceReference,
723
- };
724
- }
725
- _instructionWithinFunctionToPanicStackTraceEntry(trace, inst, errorCode) {
726
- const lastSourceReference = this._getLastSourceReference(trace);
727
- return {
728
- type: solidity_stack_trace_1.StackTraceEntryType.PANIC_ERROR,
729
- sourceReference: sourceLocationToSourceReference(trace.bytecode, inst.location) ??
730
- lastSourceReference,
731
- errorCode,
732
- };
733
- }
734
- _instructionWithinFunctionToCustomErrorStackTraceEntry(trace, inst, message) {
735
- const lastSourceReference = this._getLastSourceReference(trace);
736
- (0, errors_1.assertHardhatInvariant)(lastSourceReference !== undefined, "Expected last source reference to be defined");
737
- return {
738
- type: solidity_stack_trace_1.StackTraceEntryType.CUSTOM_ERROR,
739
- sourceReference: sourceLocationToSourceReference(trace.bytecode, inst.location) ??
740
- lastSourceReference,
741
- message,
742
- };
743
- }
744
- _solidity063MaybeUnmappedRevert(trace) {
745
- if (trace.steps.length === 0) {
746
- return false;
747
- }
748
- const lastStep = trace.steps[trace.steps.length - 1];
749
- if (!(0, message_trace_1.isEvmStep)(lastStep)) {
750
- return false;
751
- }
752
- const lastInst = trace.bytecode.getInstruction(lastStep.pc);
753
- return (semver_1.default.satisfies(trace.bytecode.compilerVersion, `^${FIRST_SOLC_VERSION_WITH_UNMAPPED_REVERTS}`) && lastInst.opcode === opcodes_1.Opcode.REVERT);
754
- }
755
- // Solidity 0.6.3 unmapped reverts special handling
756
- // For more info: https://github.com/ethereum/solidity/issues/9006
757
- _solidity063GetFrameForUnmappedRevertBeforeFunction(trace) {
758
- let revertFrame = this._solidity063GetFrameForUnmappedRevertWithinFunction(trace);
759
- if (revertFrame === undefined ||
760
- revertFrame.sourceReference === undefined) {
761
- if (trace.bytecode.contract.receive === undefined ||
762
- trace.calldata.length > 0) {
763
- if (trace.bytecode.contract.fallback !== undefined) {
764
- // Failed within the fallback
765
- const location = trace.bytecode.contract.fallback.location;
766
- revertFrame = {
767
- type: solidity_stack_trace_1.StackTraceEntryType.UNMAPPED_SOLC_0_6_3_REVERT_ERROR,
768
- sourceReference: {
769
- contract: trace.bytecode.contract.name,
770
- function: solidity_stack_trace_1.FALLBACK_FUNCTION_NAME,
771
- sourceName: location.file.sourceName,
772
- sourceContent: location.file.content,
773
- line: location.getStartingLineNumber(),
774
- range: [location.offset, location.offset + location.length],
775
- },
776
- };
777
- this._solidity063CorrectLineNumber(revertFrame);
778
- }
779
- }
780
- else {
781
- // Failed within the receive function
782
- const location = trace.bytecode.contract.receive.location;
783
- revertFrame = {
784
- type: solidity_stack_trace_1.StackTraceEntryType.UNMAPPED_SOLC_0_6_3_REVERT_ERROR,
785
- sourceReference: {
786
- contract: trace.bytecode.contract.name,
787
- function: solidity_stack_trace_1.RECEIVE_FUNCTION_NAME,
788
- sourceName: location.file.sourceName,
789
- sourceContent: location.file.content,
790
- line: location.getStartingLineNumber(),
791
- range: [location.offset, location.offset + location.length],
792
- },
793
- };
794
- this._solidity063CorrectLineNumber(revertFrame);
795
- }
796
- }
797
- return revertFrame;
798
- }
799
- _getOtherErrorBeforeCalledFunctionStackTraceEntry(trace) {
800
- return {
801
- type: solidity_stack_trace_1.StackTraceEntryType.OTHER_EXECUTION_ERROR,
802
- sourceReference: this._getContractStartWithoutFunctionSourceReference(trace),
803
- };
804
- }
805
- _isCalledNonContractAccountError(trace) {
806
- // We could change this to checking that the last valid location maps to a call, but
807
- // it's way more complex as we need to get the ast node from that location.
808
- const lastIndex = this._getLastInstructionWithValidLocationStepIndex(trace);
809
- if (lastIndex === undefined || lastIndex === 0) {
810
- return false;
811
- }
812
- const lastStep = trace.steps[lastIndex]; // We know this is an EVM step
813
- const lastInst = trace.bytecode.getInstruction(lastStep.pc);
814
- if (lastInst.opcode !== opcodes_1.Opcode.ISZERO) {
815
- return false;
816
- }
817
- const prevStep = trace.steps[lastIndex - 1]; // We know this is an EVM step
818
- const prevInst = trace.bytecode.getInstruction(prevStep.pc);
819
- return prevInst.opcode === opcodes_1.Opcode.EXTCODESIZE;
820
- }
821
- _solidity063GetFrameForUnmappedRevertWithinFunction(trace) {
822
- // If we are within a function there's a last valid location. It may
823
- // be the entire contract.
824
- const prevInst = this._getLastInstructionWithValidLocation(trace);
825
- const lastStep = trace.steps[trace.steps.length - 1];
826
- const nextInstPc = lastStep.pc + 1;
827
- const hasNextInst = trace.bytecode.hasInstruction(nextInstPc);
828
- if (hasNextInst) {
829
- const nextInst = trace.bytecode.getInstruction(nextInstPc);
830
- const prevLoc = prevInst?.location;
831
- const nextLoc = nextInst.location;
832
- const prevFunc = prevLoc?.getContainingFunction();
833
- const nextFunc = nextLoc?.getContainingFunction();
834
- // This is probably a require. This means that we have the exact
835
- // line, but the stack trace may be degraded (e.g. missing our
836
- // synthetic call frames when failing in a modifier) so we still
837
- // add this frame as UNMAPPED_SOLC_0_6_3_REVERT_ERROR
838
- if (prevFunc !== undefined &&
839
- nextLoc !== undefined &&
840
- prevLoc !== undefined &&
841
- prevLoc.equals(nextLoc)) {
842
- return this._instructionWithinFunctionToUnmappedSolc063RevertErrorStackTraceEntry(trace, nextInst);
843
- }
844
- let revertFrame;
845
- // If the previous and next location don't match, we try to use the
846
- // previous one if it's inside a function, otherwise we use the next one
847
- if (prevFunc !== undefined && prevInst !== undefined) {
848
- revertFrame =
849
- this._instructionWithinFunctionToUnmappedSolc063RevertErrorStackTraceEntry(trace, prevInst);
850
- }
851
- else if (nextFunc !== undefined) {
852
- revertFrame =
853
- this._instructionWithinFunctionToUnmappedSolc063RevertErrorStackTraceEntry(trace, nextInst);
854
- }
855
- if (revertFrame !== undefined) {
856
- this._solidity063CorrectLineNumber(revertFrame);
857
- }
858
- return revertFrame;
859
- }
860
- if ((0, message_trace_1.isCreateTrace)(trace) && prevInst !== undefined) {
861
- // Solidity is smart enough to stop emitting extra instructions after
862
- // an unconditional revert happens in a constructor. If this is the case
863
- // we just return a special error.
864
- const constructorRevertFrame = this._instructionWithinFunctionToUnmappedSolc063RevertErrorStackTraceEntry(trace, prevInst);
865
- // When the latest instruction is not within a function we need
866
- // some default sourceReference to show to the user
867
- if (constructorRevertFrame.sourceReference === undefined) {
868
- const location = trace.bytecode.contract.location;
869
- const defaultSourceReference = {
870
- function: solidity_stack_trace_1.CONSTRUCTOR_FUNCTION_NAME,
871
- contract: trace.bytecode.contract.name,
872
- sourceName: location.file.sourceName,
873
- sourceContent: location.file.content,
874
- line: location.getStartingLineNumber(),
875
- range: [location.offset, location.offset + location.length],
876
- };
877
- if (trace.bytecode.contract.constructorFunction !== undefined) {
878
- defaultSourceReference.line =
879
- trace.bytecode.contract.constructorFunction.location.getStartingLineNumber();
880
- }
881
- constructorRevertFrame.sourceReference = defaultSourceReference;
882
- }
883
- else {
884
- this._solidity063CorrectLineNumber(constructorRevertFrame);
885
- }
886
- return constructorRevertFrame;
887
- }
888
- if (prevInst !== undefined) {
889
- // We may as well just be in a function or modifier and just happen
890
- // to be at the last instruction of the runtime bytecode.
891
- // In this case we just return whatever the last mapped intruction
892
- // points to.
893
- const latestInstructionRevertFrame = this._instructionWithinFunctionToUnmappedSolc063RevertErrorStackTraceEntry(trace, prevInst);
894
- if (latestInstructionRevertFrame.sourceReference !== undefined) {
895
- this._solidity063CorrectLineNumber(latestInstructionRevertFrame);
896
- }
897
- return latestInstructionRevertFrame;
898
- }
899
- }
900
- _isContractTooLargeError(trace) {
901
- return trace.exit.kind === exit_1.ExitCode.CODESIZE_EXCEEDS_MAXIMUM;
902
- }
903
- _solidity063CorrectLineNumber(revertFrame) {
904
- if (revertFrame.sourceReference === undefined) {
905
- return;
906
- }
907
- const lines = revertFrame.sourceReference.sourceContent.split("\n");
908
- const currentLine = lines[revertFrame.sourceReference.line - 1];
909
- if (currentLine.includes("require") || currentLine.includes("revert")) {
910
- return;
911
- }
912
- const nextLines = lines.slice(revertFrame.sourceReference.line);
913
- const firstNonEmptyLine = nextLines.findIndex((l) => l.trim() !== "");
914
- if (firstNonEmptyLine === -1) {
915
- return;
916
- }
917
- const nextLine = nextLines[firstNonEmptyLine];
918
- if (nextLine.includes("require") || nextLine.includes("revert")) {
919
- revertFrame.sourceReference.line += 1 + firstNonEmptyLine;
920
- }
921
- }
922
- _getLastInstructionWithValidLocationStepIndex(trace) {
923
- for (let i = trace.steps.length - 1; i >= 0; i--) {
924
- const step = trace.steps[i];
925
- if (!(0, message_trace_1.isEvmStep)(step)) {
926
- return undefined;
927
- }
928
- const inst = trace.bytecode.getInstruction(step.pc);
929
- if (inst.location !== undefined) {
930
- return i;
931
- }
932
- }
933
- return undefined;
934
- }
935
- _getLastInstructionWithValidLocation(trace) {
936
- const lastLocationIndex = this._getLastInstructionWithValidLocationStepIndex(trace);
937
- if (lastLocationIndex === undefined) {
938
- return undefined;
939
- }
940
- const lastLocationStep = trace.steps[lastLocationIndex];
941
- if ((0, message_trace_1.isEvmStep)(lastLocationStep)) {
942
- const lastInstructionWithLocation = trace.bytecode.getInstruction(lastLocationStep.pc);
943
- return lastInstructionWithLocation;
944
- }
945
- return undefined;
946
- }
947
- _callInstructionToCallFailedToExecuteStackTraceEntry(bytecode, callInst) {
948
- const sourceReference = sourceLocationToSourceReference(bytecode, callInst.location);
949
- (0, errors_1.assertHardhatInvariant)(sourceReference !== undefined, "Expected source reference to be defined");
950
- // Calls only happen within functions
951
- return {
952
- type: solidity_stack_trace_1.StackTraceEntryType.CALL_FAILED_ERROR,
953
- sourceReference,
954
- };
955
- }
956
- _getEntryBeforeFailureInModifier(trace, functionJumpdests) {
957
- // If there's a jumpdest, this modifier belongs to the last function that it represents
958
- if (functionJumpdests.length > 0) {
959
- return instructionToCallstackStackTraceEntry(trace.bytecode, functionJumpdests[functionJumpdests.length - 1]);
960
- }
961
- // This function is only called after we jumped into the initial function in call traces, so
962
- // there should always be at least a function jumpdest.
963
- if (!(0, message_trace_1.isDecodedCreateTrace)(trace)) {
964
- throw new Error("This shouldn't happen: a call trace has no functionJumpdest but has already jumped into a function");
965
- }
966
- // If there's no jump dest, we point to the constructor.
967
- return {
968
- type: solidity_stack_trace_1.StackTraceEntryType.CALLSTACK_ENTRY,
969
- sourceReference: this._getConstructorStartSourceReference(trace),
970
- functionType: model_1.ContractFunctionType.CONSTRUCTOR,
971
- };
972
- }
973
- _failsRightAfterCall(trace, callSubtraceStepIndex) {
974
- const lastStep = trace.steps[trace.steps.length - 1];
975
- if (!(0, message_trace_1.isEvmStep)(lastStep)) {
976
- return false;
977
- }
978
- const lastInst = trace.bytecode.getInstruction(lastStep.pc);
979
- if (lastInst.opcode !== opcodes_1.Opcode.REVERT) {
980
- return false;
981
- }
982
- const callOpcodeStep = trace.steps[callSubtraceStepIndex - 1];
983
- const callInst = trace.bytecode.getInstruction(callOpcodeStep.pc);
984
- // Calls are always made from within functions
985
- (0, errors_1.assertHardhatInvariant)(callInst.location !== undefined, "Expected call instruction location to be defined");
986
- return this._isLastLocation(trace, callSubtraceStepIndex + 1, callInst.location);
987
- }
988
- _isCallFailedError(trace, instIndex, callInstruction) {
989
- const callLocation = callInstruction.location;
990
- // Calls are always made from within functions
991
- (0, errors_1.assertHardhatInvariant)(callLocation !== undefined, "Expected call location to be defined");
992
- return this._isLastLocation(trace, instIndex, callLocation);
993
- }
994
- _isLastLocation(trace, fromStep, location) {
995
- for (let i = fromStep; i < trace.steps.length; i++) {
996
- const step = trace.steps[i];
997
- if (!(0, message_trace_1.isEvmStep)(step)) {
998
- return false;
999
- }
1000
- const stepInst = trace.bytecode.getInstruction(step.pc);
1001
- if (stepInst.location === undefined) {
1002
- continue;
1003
- }
1004
- if (!location.equals(stepInst.location)) {
1005
- return false;
1006
- }
1007
- }
1008
- return true;
1009
- }
1010
- _isSubtraceErrorPropagated(trace, callSubtraceStepIndex) {
1011
- const call = trace.steps[callSubtraceStepIndex];
1012
- if (!(0, ethereumjs_util_1.equalsBytes)(trace.returnData, call.returnData)) {
1013
- return false;
1014
- }
1015
- if (trace.exit.kind === exit_1.ExitCode.OUT_OF_GAS &&
1016
- call.exit.kind === exit_1.ExitCode.OUT_OF_GAS) {
1017
- return true;
1018
- }
1019
- // If the return data is not empty, and it's still the same, we assume it
1020
- // is being propagated
1021
- if (trace.returnData.length > 0) {
1022
- return true;
1023
- }
1024
- return this._failsRightAfterCall(trace, callSubtraceStepIndex);
1025
- }
1026
- _isProxyErrorPropagated(trace, callSubtraceStepIndex) {
1027
- if (!(0, message_trace_1.isDecodedCallTrace)(trace)) {
1028
- return false;
1029
- }
1030
- const callStep = trace.steps[callSubtraceStepIndex - 1];
1031
- if (!(0, message_trace_1.isEvmStep)(callStep)) {
1032
- return false;
1033
- }
1034
- const callInst = trace.bytecode.getInstruction(callStep.pc);
1035
- if (callInst.opcode !== opcodes_1.Opcode.DELEGATECALL) {
1036
- return false;
1037
- }
1038
- const subtrace = trace.steps[callSubtraceStepIndex];
1039
- if ((0, message_trace_1.isEvmStep)(subtrace)) {
1040
- return false;
1041
- }
1042
- if ((0, message_trace_1.isPrecompileTrace)(subtrace)) {
1043
- return false;
1044
- }
1045
- // If we can't recognize the implementation we'd better don't consider it as such
1046
- if (subtrace.bytecode === undefined) {
1047
- return false;
1048
- }
1049
- if (subtrace.bytecode.contract.type === model_1.ContractType.LIBRARY) {
1050
- return false;
1051
- }
1052
- if (!(0, ethereumjs_util_1.equalsBytes)(trace.returnData, subtrace.returnData)) {
1053
- return false;
1054
- }
1055
- for (let i = callSubtraceStepIndex + 1; i < trace.steps.length; i++) {
1056
- const step = trace.steps[i];
1057
- if (!(0, message_trace_1.isEvmStep)(step)) {
1058
- return false;
1059
- }
1060
- const inst = trace.bytecode.getInstruction(step.pc);
1061
- // All the remaining locations should be valid, as they are part of the inline asm
1062
- if (inst.location === undefined) {
1063
- return false;
1064
- }
1065
- if (inst.jumpType === model_1.JumpType.INTO_FUNCTION ||
1066
- inst.jumpType === model_1.JumpType.OUTOF_FUNCTION) {
1067
- return false;
1068
- }
1069
- }
1070
- const lastStep = trace.steps[trace.steps.length - 1];
1071
- const lastInst = trace.bytecode.getInstruction(lastStep.pc);
1072
- return lastInst.opcode === opcodes_1.Opcode.REVERT;
1073
- }
1074
- _isContractCallRunOutOfGasError(trace, callStepIndex) {
1075
- if (trace.returnData.length > 0) {
1076
- return false;
1077
- }
1078
- if (trace.exit.kind !== exit_1.ExitCode.REVERT) {
1079
- return false;
1080
- }
1081
- const call = trace.steps[callStepIndex];
1082
- if (call.exit.kind !== exit_1.ExitCode.OUT_OF_GAS) {
1083
- return false;
1084
- }
1085
- return this._failsRightAfterCall(trace, callStepIndex);
1086
- }
1087
- _isPanicReturnData(returnData) {
1088
- return new return_data_1.ReturnData(returnData).isPanicReturnData();
1089
- }
1090
- }
1091
- exports.ErrorInferrer = ErrorInferrer;
1092
- function instructionToCallstackStackTraceEntry(bytecode, inst) {
1093
- // This means that a jump is made from within an internal solc function.
1094
- // These are normally made from yul code, so they don't map to any Solidity
1095
- // function
1096
- if (inst.location === undefined) {
1097
- const location = bytecode.contract.location;
1098
- return {
1099
- type: solidity_stack_trace_1.StackTraceEntryType.INTERNAL_FUNCTION_CALLSTACK_ENTRY,
1100
- pc: inst.pc,
1101
- sourceReference: {
1102
- sourceName: bytecode.contract.location.file.sourceName,
1103
- sourceContent: bytecode.contract.location.file.content,
1104
- contract: bytecode.contract.name,
1105
- function: undefined,
1106
- line: bytecode.contract.location.getStartingLineNumber(),
1107
- range: [location.offset, location.offset + location.length],
1108
- },
1109
- };
1110
- }
1111
- const func = inst.location?.getContainingFunction();
1112
- if (func !== undefined) {
1113
- const sourceReference = sourceLocationToSourceReference(bytecode, inst.location);
1114
- (0, errors_1.assertHardhatInvariant)(sourceReference !== undefined, "Expected source reference to be defined");
1115
- return {
1116
- type: solidity_stack_trace_1.StackTraceEntryType.CALLSTACK_ENTRY,
1117
- sourceReference,
1118
- functionType: func.type,
1119
- };
1120
- }
1121
- (0, errors_1.assertHardhatInvariant)(inst.location !== undefined, "Expected instruction location to be defined");
1122
- return {
1123
- type: solidity_stack_trace_1.StackTraceEntryType.CALLSTACK_ENTRY,
1124
- sourceReference: {
1125
- function: undefined,
1126
- contract: bytecode.contract.name,
1127
- sourceName: inst.location.file.sourceName,
1128
- sourceContent: inst.location.file.content,
1129
- line: inst.location.getStartingLineNumber(),
1130
- range: [
1131
- inst.location.offset,
1132
- inst.location.offset + inst.location.length,
1133
- ],
1134
- },
1135
- functionType: model_1.ContractFunctionType.FUNCTION,
1136
- };
1137
- }
1138
- exports.instructionToCallstackStackTraceEntry = instructionToCallstackStackTraceEntry;
1139
- function sourceLocationToSourceReference(bytecode, location) {
1140
- if (location === undefined) {
1141
- return undefined;
1142
- }
1143
- const func = location.getContainingFunction();
1144
- if (func === undefined) {
1145
- return undefined;
1146
- }
1147
- let funcName = func.name;
1148
- if (func.type === model_1.ContractFunctionType.CONSTRUCTOR) {
1149
- funcName = solidity_stack_trace_1.CONSTRUCTOR_FUNCTION_NAME;
1150
- }
1151
- else if (func.type === model_1.ContractFunctionType.FALLBACK) {
1152
- funcName = solidity_stack_trace_1.FALLBACK_FUNCTION_NAME;
1153
- }
1154
- else if (func.type === model_1.ContractFunctionType.RECEIVE) {
1155
- funcName = solidity_stack_trace_1.RECEIVE_FUNCTION_NAME;
1156
- }
1157
- return {
1158
- function: funcName,
1159
- contract: func.type === model_1.ContractFunctionType.FREE_FUNCTION
1160
- ? undefined
1161
- : bytecode.contract.name,
1162
- sourceName: func.location.file.sourceName,
1163
- sourceContent: func.location.file.content,
1164
- line: location.getStartingLineNumber(),
1165
- range: [location.offset, location.offset + location.length],
1166
- };
1167
- }
1168
- //# sourceMappingURL=error-inferrer.js.map