hardhat 2.22.11 → 2.22.13
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/internal/hardhat-network/provider/provider.d.ts +2 -3
- package/internal/hardhat-network/provider/provider.d.ts.map +1 -1
- package/internal/hardhat-network/provider/provider.js +5 -19
- package/internal/hardhat-network/provider/provider.js.map +1 -1
- package/internal/hardhat-network/provider/return-data.d.ts +2 -15
- package/internal/hardhat-network/provider/return-data.d.ts.map +1 -1
- package/internal/hardhat-network/provider/return-data.js +2 -50
- package/internal/hardhat-network/provider/return-data.js.map +1 -1
- package/internal/hardhat-network/provider/vm/exit.d.ts +2 -20
- package/internal/hardhat-network/provider/vm/exit.d.ts.map +1 -1
- package/internal/hardhat-network/provider/vm/exit.js +3 -78
- package/internal/hardhat-network/provider/vm/exit.js.map +1 -1
- package/internal/hardhat-network/stack-traces/compiler-to-model.d.ts +2 -3
- package/internal/hardhat-network/stack-traces/compiler-to-model.d.ts.map +1 -1
- package/internal/hardhat-network/stack-traces/compiler-to-model.js +2 -351
- package/internal/hardhat-network/stack-traces/compiler-to-model.js.map +1 -1
- package/internal/hardhat-network/stack-traces/debug.d.ts +2 -7
- package/internal/hardhat-network/stack-traces/debug.d.ts.map +1 -1
- package/internal/hardhat-network/stack-traces/debug.js +3 -143
- package/internal/hardhat-network/stack-traces/debug.js.map +1 -1
- package/internal/hardhat-network/stack-traces/library-utils.d.ts +2 -11
- package/internal/hardhat-network/stack-traces/library-utils.d.ts.map +1 -1
- package/internal/hardhat-network/stack-traces/library-utils.js +3 -61
- package/internal/hardhat-network/stack-traces/library-utils.js.map +1 -1
- package/internal/hardhat-network/stack-traces/logger.d.ts.map +1 -1
- package/internal/hardhat-network/stack-traces/logger.js +0 -221
- package/internal/hardhat-network/stack-traces/logger.js.map +1 -1
- package/internal/hardhat-network/stack-traces/message-trace.d.ts +2 -51
- package/internal/hardhat-network/stack-traces/message-trace.d.ts.map +1 -1
- package/internal/hardhat-network/stack-traces/message-trace.js +0 -46
- package/internal/hardhat-network/stack-traces/message-trace.js.map +1 -1
- package/internal/hardhat-network/stack-traces/solidity-errors.d.ts.map +1 -1
- package/internal/hardhat-network/stack-traces/solidity-errors.js +58 -53
- package/internal/hardhat-network/stack-traces/solidity-errors.js.map +1 -1
- package/internal/hardhat-network/stack-traces/solidity-stack-trace.d.ts +4 -155
- package/internal/hardhat-network/stack-traces/solidity-stack-trace.d.ts.map +1 -1
- package/internal/hardhat-network/stack-traces/solidity-stack-trace.js +12 -37
- package/internal/hardhat-network/stack-traces/solidity-stack-trace.js.map +1 -1
- package/internal/hardhat-network/stack-traces/solidityTracer.d.ts +2 -13
- package/internal/hardhat-network/stack-traces/solidityTracer.d.ts.map +1 -1
- package/internal/hardhat-network/stack-traces/solidityTracer.js +2 -162
- package/internal/hardhat-network/stack-traces/solidityTracer.js.map +1 -1
- package/internal/hardhat-network/stack-traces/vm-trace-decoder.d.ts +4 -15
- package/internal/hardhat-network/stack-traces/vm-trace-decoder.d.ts.map +1 -1
- package/internal/hardhat-network/stack-traces/vm-trace-decoder.js +6 -70
- package/internal/hardhat-network/stack-traces/vm-trace-decoder.js.map +1 -1
- package/internal/hardhat-network/stack-traces/vm-tracer.d.ts +2 -19
- package/internal/hardhat-network/stack-traces/vm-tracer.d.ts.map +1 -1
- package/internal/hardhat-network/stack-traces/vm-tracer.js +3 -150
- package/internal/hardhat-network/stack-traces/vm-tracer.js.map +1 -1
- package/package.json +2 -2
- package/src/internal/hardhat-network/provider/provider.ts +11 -24
- package/src/internal/hardhat-network/provider/return-data.ts +5 -73
- package/src/internal/hardhat-network/provider/vm/exit.ts +4 -92
- package/src/internal/hardhat-network/stack-traces/compiler-to-model.ts +5 -697
- package/src/internal/hardhat-network/stack-traces/debug.ts +5 -218
- package/src/internal/hardhat-network/stack-traces/library-utils.ts +5 -90
- package/src/internal/hardhat-network/stack-traces/logger.ts +0 -221
- package/src/internal/hardhat-network/stack-traces/message-trace.ts +5 -122
- package/src/internal/hardhat-network/stack-traces/solidity-errors.ts +16 -15
- package/src/internal/hardhat-network/stack-traces/solidity-stack-trace.ts +83 -186
- package/src/internal/hardhat-network/stack-traces/solidityTracer.ts +5 -253
- package/src/internal/hardhat-network/stack-traces/vm-trace-decoder.ts +15 -108
- package/src/internal/hardhat-network/stack-traces/vm-tracer.ts +5 -206
- package/internal/hardhat-network/stack-traces/contracts-identifier.d.ts +0 -15
- package/internal/hardhat-network/stack-traces/contracts-identifier.d.ts.map +0 -1
- package/internal/hardhat-network/stack-traces/contracts-identifier.js +0 -166
- package/internal/hardhat-network/stack-traces/contracts-identifier.js.map +0 -1
- package/internal/hardhat-network/stack-traces/error-inferrer.d.ts +0 -85
- package/internal/hardhat-network/stack-traces/error-inferrer.d.ts.map +0 -1
- package/internal/hardhat-network/stack-traces/error-inferrer.js +0 -1168
- package/internal/hardhat-network/stack-traces/error-inferrer.js.map +0 -1
- package/internal/hardhat-network/stack-traces/mapped-inlined-internal-functions-heuristics.d.ts +0 -24
- package/internal/hardhat-network/stack-traces/mapped-inlined-internal-functions-heuristics.d.ts.map +0 -1
- package/internal/hardhat-network/stack-traces/mapped-inlined-internal-functions-heuristics.js +0 -116
- package/internal/hardhat-network/stack-traces/mapped-inlined-internal-functions-heuristics.js.map +0 -1
- package/internal/hardhat-network/stack-traces/model.d.ts +0 -140
- package/internal/hardhat-network/stack-traces/model.d.ts.map +0 -1
- package/internal/hardhat-network/stack-traces/model.js +0 -328
- package/internal/hardhat-network/stack-traces/model.js.map +0 -1
- package/internal/hardhat-network/stack-traces/opcodes.d.ts +0 -266
- package/internal/hardhat-network/stack-traces/opcodes.d.ts.map +0 -1
- package/internal/hardhat-network/stack-traces/opcodes.js +0 -320
- package/internal/hardhat-network/stack-traces/opcodes.js.map +0 -1
- package/internal/hardhat-network/stack-traces/source-maps.d.ts +0 -13
- package/internal/hardhat-network/stack-traces/source-maps.d.ts.map +0 -1
- package/internal/hardhat-network/stack-traces/source-maps.js +0 -106
- package/internal/hardhat-network/stack-traces/source-maps.js.map +0 -1
- package/src/internal/hardhat-network/stack-traces/contracts-identifier.ts +0 -235
- package/src/internal/hardhat-network/stack-traces/error-inferrer.ts +0 -1845
- package/src/internal/hardhat-network/stack-traces/mapped-inlined-internal-functions-heuristics.ts +0 -163
- package/src/internal/hardhat-network/stack-traces/model.ts +0 -409
- package/src/internal/hardhat-network/stack-traces/opcodes.ts +0 -344
- package/src/internal/hardhat-network/stack-traces/source-maps.ts +0 -167
|
@@ -1,699 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { requireNapiRsModule } from "../../../common/napi-rs";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
CompilerOutputBytecode,
|
|
7
|
-
} from "../../../types";
|
|
3
|
+
const { createModelsAndDecodeBytecodes } = requireNapiRsModule(
|
|
4
|
+
"@nomicfoundation/edr"
|
|
5
|
+
) as typeof import("@nomicfoundation/edr");
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
getLibraryAddressPositions,
|
|
11
|
-
normalizeCompilerOutputBytecode,
|
|
12
|
-
} from "./library-utils";
|
|
13
|
-
import {
|
|
14
|
-
Bytecode,
|
|
15
|
-
Contract,
|
|
16
|
-
ContractFunction,
|
|
17
|
-
ContractFunctionType,
|
|
18
|
-
ContractFunctionVisibility,
|
|
19
|
-
ContractType,
|
|
20
|
-
CustomError,
|
|
21
|
-
SourceFile,
|
|
22
|
-
SourceLocation,
|
|
23
|
-
} from "./model";
|
|
24
|
-
import { decodeInstructions } from "./source-maps";
|
|
25
|
-
|
|
26
|
-
const abi = require("ethereumjs-abi");
|
|
27
|
-
|
|
28
|
-
const log = debug("hardhat:core:hardhat-network:compiler-to-model");
|
|
29
|
-
|
|
30
|
-
interface ContractAbiEntry {
|
|
31
|
-
name?: string;
|
|
32
|
-
inputs?: Array<{
|
|
33
|
-
type: string;
|
|
34
|
-
}>;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
type ContractAbi = ContractAbiEntry[];
|
|
38
|
-
|
|
39
|
-
export function createModelsAndDecodeBytecodes(
|
|
40
|
-
solcVersion: string,
|
|
41
|
-
compilerInput: CompilerInput,
|
|
42
|
-
compilerOutput: CompilerOutput
|
|
43
|
-
): Bytecode[] {
|
|
44
|
-
const fileIdToSourceFile = new Map<number, SourceFile>();
|
|
45
|
-
const contractIdToContract = new Map<number, Contract>();
|
|
46
|
-
|
|
47
|
-
createSourcesModelFromAst(
|
|
48
|
-
compilerOutput,
|
|
49
|
-
compilerInput,
|
|
50
|
-
fileIdToSourceFile,
|
|
51
|
-
contractIdToContract
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
const bytecodes = decodeBytecodes(
|
|
55
|
-
solcVersion,
|
|
56
|
-
compilerOutput,
|
|
57
|
-
fileIdToSourceFile,
|
|
58
|
-
contractIdToContract
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
correctSelectors(bytecodes, compilerOutput);
|
|
62
|
-
|
|
63
|
-
return bytecodes;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function createSourcesModelFromAst(
|
|
67
|
-
compilerOutput: CompilerOutput,
|
|
68
|
-
compilerInput: CompilerInput,
|
|
69
|
-
fileIdToSourceFile: Map<number, SourceFile>,
|
|
70
|
-
contractIdToContract: Map<number, Contract>
|
|
71
|
-
) {
|
|
72
|
-
const contractIdToLinearizedBaseContractIds = new Map<number, number[]>();
|
|
73
|
-
|
|
74
|
-
// Create a `sourceName => contract => abi` mapping
|
|
75
|
-
const sourceNameToContractToAbi = new Map<string, Map<string, ContractAbi>>();
|
|
76
|
-
for (const [sourceName, contracts] of Object.entries(
|
|
77
|
-
compilerOutput.contracts
|
|
78
|
-
)) {
|
|
79
|
-
const contractToAbi = new Map<string, ContractAbi>();
|
|
80
|
-
sourceNameToContractToAbi.set(sourceName, contractToAbi);
|
|
81
|
-
for (const [contractName, contract] of Object.entries(contracts)) {
|
|
82
|
-
contractToAbi.set(contractName, contract.abi);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
for (const [sourceName, source] of Object.entries(compilerOutput.sources)) {
|
|
87
|
-
const contractToAbi = sourceNameToContractToAbi.get(sourceName);
|
|
88
|
-
const file = new SourceFile(
|
|
89
|
-
sourceName,
|
|
90
|
-
compilerInput.sources[sourceName].content
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
fileIdToSourceFile.set(source.id, file);
|
|
94
|
-
|
|
95
|
-
for (const node of source.ast.nodes) {
|
|
96
|
-
if (node.nodeType === "ContractDefinition") {
|
|
97
|
-
const contractType = contractKindToContractType(node.contractKind);
|
|
98
|
-
|
|
99
|
-
if (contractType === undefined) {
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const contractAbi = contractToAbi?.get(node.name);
|
|
104
|
-
|
|
105
|
-
processContractAstNode(
|
|
106
|
-
file,
|
|
107
|
-
node,
|
|
108
|
-
fileIdToSourceFile,
|
|
109
|
-
contractType,
|
|
110
|
-
contractIdToContract,
|
|
111
|
-
contractIdToLinearizedBaseContractIds,
|
|
112
|
-
contractAbi
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// top-level functions
|
|
117
|
-
if (node.nodeType === "FunctionDefinition") {
|
|
118
|
-
processFunctionDefinitionAstNode(
|
|
119
|
-
node,
|
|
120
|
-
fileIdToSourceFile,
|
|
121
|
-
undefined,
|
|
122
|
-
file
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
applyContractsInheritance(
|
|
129
|
-
contractIdToContract,
|
|
130
|
-
contractIdToLinearizedBaseContractIds
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function processContractAstNode(
|
|
135
|
-
file: SourceFile,
|
|
136
|
-
contractNode: any,
|
|
137
|
-
fileIdToSourceFile: Map<number, SourceFile>,
|
|
138
|
-
contractType: ContractType,
|
|
139
|
-
contractIdToContract: Map<number, Contract>,
|
|
140
|
-
contractIdToLinearizedBaseContractIds: Map<number, number[]>,
|
|
141
|
-
contractAbi?: ContractAbi
|
|
142
|
-
) {
|
|
143
|
-
const contractLocation = astSrcToSourceLocation(
|
|
144
|
-
contractNode.src,
|
|
145
|
-
fileIdToSourceFile
|
|
146
|
-
)!;
|
|
147
|
-
|
|
148
|
-
const contract = new Contract(
|
|
149
|
-
contractNode.name,
|
|
150
|
-
contractType,
|
|
151
|
-
contractLocation
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
contractIdToContract.set(contractNode.id, contract);
|
|
155
|
-
contractIdToLinearizedBaseContractIds.set(
|
|
156
|
-
contractNode.id,
|
|
157
|
-
contractNode.linearizedBaseContracts
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
file.addContract(contract);
|
|
161
|
-
|
|
162
|
-
for (const node of contractNode.nodes) {
|
|
163
|
-
if (node.nodeType === "FunctionDefinition") {
|
|
164
|
-
const functionAbis = contractAbi?.filter(
|
|
165
|
-
(abiEntry) => abiEntry.name === node.name
|
|
166
|
-
);
|
|
167
|
-
|
|
168
|
-
processFunctionDefinitionAstNode(
|
|
169
|
-
node,
|
|
170
|
-
fileIdToSourceFile,
|
|
171
|
-
contract,
|
|
172
|
-
file,
|
|
173
|
-
functionAbis
|
|
174
|
-
);
|
|
175
|
-
} else if (node.nodeType === "ModifierDefinition") {
|
|
176
|
-
processModifierDefinitionAstNode(
|
|
177
|
-
node,
|
|
178
|
-
fileIdToSourceFile,
|
|
179
|
-
contract,
|
|
180
|
-
file
|
|
181
|
-
);
|
|
182
|
-
} else if (node.nodeType === "VariableDeclaration") {
|
|
183
|
-
const getterAbi = contractAbi?.find(
|
|
184
|
-
(abiEntry) => abiEntry.name === node.name
|
|
185
|
-
);
|
|
186
|
-
processVariableDeclarationAstNode(
|
|
187
|
-
node,
|
|
188
|
-
fileIdToSourceFile,
|
|
189
|
-
contract,
|
|
190
|
-
file,
|
|
191
|
-
getterAbi
|
|
192
|
-
);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
function processFunctionDefinitionAstNode(
|
|
198
|
-
functionDefinitionNode: any,
|
|
199
|
-
fileIdToSourceFile: Map<number, SourceFile>,
|
|
200
|
-
contract: Contract | undefined,
|
|
201
|
-
file: SourceFile,
|
|
202
|
-
functionAbis?: ContractAbiEntry[]
|
|
203
|
-
) {
|
|
204
|
-
if (functionDefinitionNode.implemented === false) {
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
const functionType = functionDefinitionKindToFunctionType(
|
|
209
|
-
functionDefinitionNode.kind
|
|
210
|
-
);
|
|
211
|
-
const functionLocation = astSrcToSourceLocation(
|
|
212
|
-
functionDefinitionNode.src,
|
|
213
|
-
fileIdToSourceFile
|
|
214
|
-
)!;
|
|
215
|
-
const visibility = astVisibilityToVisibility(
|
|
216
|
-
functionDefinitionNode.visibility
|
|
217
|
-
);
|
|
218
|
-
|
|
219
|
-
let selector: Buffer | undefined;
|
|
220
|
-
if (
|
|
221
|
-
functionType === ContractFunctionType.FUNCTION &&
|
|
222
|
-
(visibility === ContractFunctionVisibility.EXTERNAL ||
|
|
223
|
-
visibility === ContractFunctionVisibility.PUBLIC)
|
|
224
|
-
) {
|
|
225
|
-
selector = astFunctionDefinitionToSelector(functionDefinitionNode);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// function can be overloaded, match the abi by the selector
|
|
229
|
-
const matchingFunctionAbi = functionAbis?.find((functionAbi) => {
|
|
230
|
-
if (functionAbi.name === undefined) {
|
|
231
|
-
return false;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const functionAbiSelector = abi.methodID(
|
|
235
|
-
functionAbi.name,
|
|
236
|
-
functionAbi.inputs?.map((input) => input.type) ?? []
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
if (selector === undefined || functionAbiSelector === undefined) {
|
|
240
|
-
return false;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
return selector.equals(functionAbiSelector);
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
const paramTypes = matchingFunctionAbi?.inputs?.map((input) => input.type);
|
|
247
|
-
|
|
248
|
-
const cf = new ContractFunction(
|
|
249
|
-
functionDefinitionNode.name,
|
|
250
|
-
functionType,
|
|
251
|
-
functionLocation,
|
|
252
|
-
contract,
|
|
253
|
-
visibility,
|
|
254
|
-
functionDefinitionNode.stateMutability === "payable",
|
|
255
|
-
selector,
|
|
256
|
-
paramTypes
|
|
257
|
-
);
|
|
258
|
-
|
|
259
|
-
if (contract !== undefined) {
|
|
260
|
-
contract.addLocalFunction(cf);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
file.addFunction(cf);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
function processModifierDefinitionAstNode(
|
|
267
|
-
modifierDefinitionNode: any,
|
|
268
|
-
fileIdToSourceFile: Map<number, SourceFile>,
|
|
269
|
-
contract: Contract,
|
|
270
|
-
file: SourceFile
|
|
271
|
-
) {
|
|
272
|
-
const functionLocation = astSrcToSourceLocation(
|
|
273
|
-
modifierDefinitionNode.src,
|
|
274
|
-
fileIdToSourceFile
|
|
275
|
-
)!;
|
|
276
|
-
|
|
277
|
-
const cf = new ContractFunction(
|
|
278
|
-
modifierDefinitionNode.name,
|
|
279
|
-
ContractFunctionType.MODIFIER,
|
|
280
|
-
functionLocation,
|
|
281
|
-
contract
|
|
282
|
-
);
|
|
283
|
-
|
|
284
|
-
contract.addLocalFunction(cf);
|
|
285
|
-
file.addFunction(cf);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function canonicalAbiTypeForElementaryOrUserDefinedTypes(keyType: any): any {
|
|
289
|
-
if (isElementaryType(keyType)) {
|
|
290
|
-
return toCanonicalAbiType(keyType.name);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
if (isEnumType(keyType)) {
|
|
294
|
-
return "uint256";
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (isContractType(keyType)) {
|
|
298
|
-
return "address";
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
return undefined;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
function getPublicVariableSelectorFromDeclarationAstNode(
|
|
305
|
-
variableDeclaration: any
|
|
306
|
-
) {
|
|
307
|
-
if (variableDeclaration.functionSelector !== undefined) {
|
|
308
|
-
return Buffer.from(variableDeclaration.functionSelector, "hex");
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
const paramTypes: string[] = [];
|
|
312
|
-
|
|
313
|
-
// VariableDeclaration nodes for function parameters or state variables will always
|
|
314
|
-
// have their typeName fields defined.
|
|
315
|
-
let nextType = variableDeclaration.typeName;
|
|
316
|
-
while (true) {
|
|
317
|
-
if (nextType.nodeType === "Mapping") {
|
|
318
|
-
const canonicalType = canonicalAbiTypeForElementaryOrUserDefinedTypes(
|
|
319
|
-
nextType.keyType
|
|
320
|
-
);
|
|
321
|
-
paramTypes.push(canonicalType);
|
|
322
|
-
|
|
323
|
-
nextType = nextType.valueType;
|
|
324
|
-
} else {
|
|
325
|
-
if (nextType.nodeType === "ArrayTypeName") {
|
|
326
|
-
paramTypes.push("uint256");
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
break;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
return abi.methodID(variableDeclaration.name, paramTypes);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
function processVariableDeclarationAstNode(
|
|
337
|
-
variableDeclarationNode: any,
|
|
338
|
-
fileIdToSourceFile: Map<number, SourceFile>,
|
|
339
|
-
contract: Contract,
|
|
340
|
-
file: SourceFile,
|
|
341
|
-
getterAbi?: ContractAbiEntry
|
|
342
|
-
) {
|
|
343
|
-
const visibility = astVisibilityToVisibility(
|
|
344
|
-
variableDeclarationNode.visibility
|
|
345
|
-
);
|
|
346
|
-
|
|
347
|
-
// Variables can't be external
|
|
348
|
-
if (visibility !== ContractFunctionVisibility.PUBLIC) {
|
|
349
|
-
return;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
const functionLocation = astSrcToSourceLocation(
|
|
353
|
-
variableDeclarationNode.src,
|
|
354
|
-
fileIdToSourceFile
|
|
355
|
-
)!;
|
|
356
|
-
|
|
357
|
-
const paramTypes = getterAbi?.inputs?.map((input) => input.type);
|
|
358
|
-
|
|
359
|
-
const cf = new ContractFunction(
|
|
360
|
-
variableDeclarationNode.name,
|
|
361
|
-
ContractFunctionType.GETTER,
|
|
362
|
-
functionLocation,
|
|
363
|
-
contract,
|
|
364
|
-
visibility,
|
|
365
|
-
false, // Getters aren't payable
|
|
366
|
-
getPublicVariableSelectorFromDeclarationAstNode(variableDeclarationNode),
|
|
367
|
-
paramTypes
|
|
368
|
-
);
|
|
369
|
-
|
|
370
|
-
contract.addLocalFunction(cf);
|
|
371
|
-
file.addFunction(cf);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
function applyContractsInheritance(
|
|
375
|
-
contractIdToContract: Map<number, Contract>,
|
|
376
|
-
contractIdToLinearizedBaseContractIds: Map<number, number[]>
|
|
377
|
-
) {
|
|
378
|
-
for (const [cid, contract] of contractIdToContract.entries()) {
|
|
379
|
-
const inheritanceIds = contractIdToLinearizedBaseContractIds.get(cid)!;
|
|
380
|
-
|
|
381
|
-
for (const baseId of inheritanceIds) {
|
|
382
|
-
const baseContract = contractIdToContract.get(baseId);
|
|
383
|
-
|
|
384
|
-
if (baseContract === undefined) {
|
|
385
|
-
// This list includes interface, which we don't model
|
|
386
|
-
continue;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
contract.addNextLinearizedBaseContract(baseContract);
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
function decodeBytecodes(
|
|
395
|
-
solcVersion: string,
|
|
396
|
-
compilerOutput: CompilerOutput,
|
|
397
|
-
fileIdToSourceFile: Map<number, SourceFile>,
|
|
398
|
-
contractIdToContract: Map<number, Contract>
|
|
399
|
-
): Bytecode[] {
|
|
400
|
-
const bytecodes: Bytecode[] = [];
|
|
401
|
-
|
|
402
|
-
for (const contract of contractIdToContract.values()) {
|
|
403
|
-
const contractFile = contract.location.file.sourceName;
|
|
404
|
-
const contractEvmOutput =
|
|
405
|
-
compilerOutput.contracts[contractFile][contract.name].evm;
|
|
406
|
-
const contractAbiOutput =
|
|
407
|
-
compilerOutput.contracts[contractFile][contract.name].abi;
|
|
408
|
-
|
|
409
|
-
for (const abiItem of contractAbiOutput) {
|
|
410
|
-
if (abiItem.type === "error") {
|
|
411
|
-
const customError = CustomError.fromABI(abiItem.name, abiItem.inputs);
|
|
412
|
-
|
|
413
|
-
if (customError !== undefined) {
|
|
414
|
-
contract.addCustomError(customError);
|
|
415
|
-
} else {
|
|
416
|
-
log(`Couldn't build CustomError for error '${abiItem.name}'`);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// This is an abstract contract
|
|
422
|
-
if (contractEvmOutput.bytecode.object === "") {
|
|
423
|
-
continue;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
const deploymentBytecode = decodeEvmBytecode(
|
|
427
|
-
contract,
|
|
428
|
-
solcVersion,
|
|
429
|
-
true,
|
|
430
|
-
contractEvmOutput.bytecode,
|
|
431
|
-
fileIdToSourceFile
|
|
432
|
-
);
|
|
433
|
-
|
|
434
|
-
const runtimeBytecode = decodeEvmBytecode(
|
|
435
|
-
contract,
|
|
436
|
-
solcVersion,
|
|
437
|
-
false,
|
|
438
|
-
contractEvmOutput.deployedBytecode,
|
|
439
|
-
fileIdToSourceFile
|
|
440
|
-
);
|
|
441
|
-
|
|
442
|
-
bytecodes.push(deploymentBytecode);
|
|
443
|
-
bytecodes.push(runtimeBytecode);
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
return bytecodes;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
function decodeEvmBytecode(
|
|
450
|
-
contract: Contract,
|
|
451
|
-
solcVersion: string,
|
|
452
|
-
isDeployment: boolean,
|
|
453
|
-
compilerBytecode: CompilerOutputBytecode,
|
|
454
|
-
fileIdToSourceFile: Map<number, SourceFile>
|
|
455
|
-
): Bytecode {
|
|
456
|
-
const libraryAddressPositions = getLibraryAddressPositions(compilerBytecode);
|
|
457
|
-
|
|
458
|
-
const immutableReferences =
|
|
459
|
-
compilerBytecode.immutableReferences !== undefined
|
|
460
|
-
? Object.values(compilerBytecode.immutableReferences).reduce(
|
|
461
|
-
(previousValue, currentValue) => [...previousValue, ...currentValue],
|
|
462
|
-
[]
|
|
463
|
-
)
|
|
464
|
-
: [];
|
|
465
|
-
|
|
466
|
-
const normalizedCode = normalizeCompilerOutputBytecode(
|
|
467
|
-
compilerBytecode.object,
|
|
468
|
-
libraryAddressPositions
|
|
469
|
-
);
|
|
470
|
-
|
|
471
|
-
const instructions = decodeInstructions(
|
|
472
|
-
normalizedCode,
|
|
473
|
-
compilerBytecode.sourceMap,
|
|
474
|
-
fileIdToSourceFile,
|
|
475
|
-
isDeployment
|
|
476
|
-
);
|
|
477
|
-
|
|
478
|
-
return new Bytecode(
|
|
479
|
-
contract,
|
|
480
|
-
isDeployment,
|
|
481
|
-
normalizedCode,
|
|
482
|
-
instructions,
|
|
483
|
-
libraryAddressPositions,
|
|
484
|
-
immutableReferences,
|
|
485
|
-
solcVersion
|
|
486
|
-
);
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
function astSrcToSourceLocation(
|
|
490
|
-
src: string,
|
|
491
|
-
fileIdToSourceFile: Map<number, SourceFile>
|
|
492
|
-
): SourceLocation | undefined {
|
|
493
|
-
const [offset, length, fileId] = src.split(":").map((p) => +p);
|
|
494
|
-
const file = fileIdToSourceFile.get(fileId);
|
|
495
|
-
|
|
496
|
-
if (file === undefined) {
|
|
497
|
-
return undefined;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
return new SourceLocation(file, offset, length);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
function contractKindToContractType(
|
|
504
|
-
contractKind?: string
|
|
505
|
-
): ContractType | undefined {
|
|
506
|
-
if (contractKind === "library") {
|
|
507
|
-
return ContractType.LIBRARY;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
if (contractKind === "contract") {
|
|
511
|
-
return ContractType.CONTRACT;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
return undefined;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
function astVisibilityToVisibility(
|
|
518
|
-
visibility: string
|
|
519
|
-
): ContractFunctionVisibility {
|
|
520
|
-
if (visibility === "private") {
|
|
521
|
-
return ContractFunctionVisibility.PRIVATE;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
if (visibility === "internal") {
|
|
525
|
-
return ContractFunctionVisibility.INTERNAL;
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
if (visibility === "public") {
|
|
529
|
-
return ContractFunctionVisibility.PUBLIC;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
return ContractFunctionVisibility.EXTERNAL;
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
function functionDefinitionKindToFunctionType(
|
|
536
|
-
kind: string | undefined
|
|
537
|
-
): ContractFunctionType {
|
|
538
|
-
if (kind === "constructor") {
|
|
539
|
-
return ContractFunctionType.CONSTRUCTOR;
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
if (kind === "fallback") {
|
|
543
|
-
return ContractFunctionType.FALLBACK;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
if (kind === "receive") {
|
|
547
|
-
return ContractFunctionType.RECEIVE;
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
if (kind === "freeFunction") {
|
|
551
|
-
return ContractFunctionType.FREE_FUNCTION;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
return ContractFunctionType.FUNCTION;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
function astFunctionDefinitionToSelector(functionDefinition: any): Buffer {
|
|
558
|
-
const paramTypes: string[] = [];
|
|
559
|
-
|
|
560
|
-
// The function selector is available in solc versions >=0.6.0
|
|
561
|
-
if (functionDefinition.functionSelector !== undefined) {
|
|
562
|
-
return Buffer.from(functionDefinition.functionSelector, "hex");
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
for (const param of functionDefinition.parameters.parameters) {
|
|
566
|
-
if (isContractType(param)) {
|
|
567
|
-
paramTypes.push("address");
|
|
568
|
-
continue;
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
// TODO: implement ABIv2 structs parsing
|
|
572
|
-
// This might mean we need to parse struct definitions before
|
|
573
|
-
// resolving types and trying to calculate function selectors.
|
|
574
|
-
// if (isStructType(param)) {
|
|
575
|
-
// paramTypes.push(something);
|
|
576
|
-
// continue;
|
|
577
|
-
// }
|
|
578
|
-
|
|
579
|
-
if (isEnumType(param)) {
|
|
580
|
-
// TODO: If the enum has >= 256 elements this will fail. It should be a uint16. This is
|
|
581
|
-
// complicated, as enums can be inherited. Fortunately, if multiple parent contracts
|
|
582
|
-
// define the same enum, solc fails to compile.
|
|
583
|
-
paramTypes.push("uint8");
|
|
584
|
-
continue;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
// The rest of the function parameters always have their typeName node defined
|
|
588
|
-
const typename = param.typeName;
|
|
589
|
-
if (
|
|
590
|
-
typename.nodeType === "ArrayTypeName" ||
|
|
591
|
-
typename.nodeType === "FunctionTypeName" ||
|
|
592
|
-
typename.nodeType === "Mapping"
|
|
593
|
-
) {
|
|
594
|
-
paramTypes.push(typename.typeDescriptions.typeString);
|
|
595
|
-
continue;
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
paramTypes.push(toCanonicalAbiType(typename.name));
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
return abi.methodID(functionDefinition.name, paramTypes);
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
function isContractType(param: any): boolean {
|
|
605
|
-
return (
|
|
606
|
-
(param.typeName?.nodeType === "UserDefinedTypeName" ||
|
|
607
|
-
param?.nodeType === "UserDefinedTypeName") &&
|
|
608
|
-
param.typeDescriptions?.typeString !== undefined &&
|
|
609
|
-
param.typeDescriptions.typeString.startsWith("contract ")
|
|
610
|
-
);
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
function isEnumType(param: any): boolean {
|
|
614
|
-
return (
|
|
615
|
-
(param.typeName?.nodeType === "UserDefinedTypeName" ||
|
|
616
|
-
param?.nodeType === "UserDefinedTypeName") &&
|
|
617
|
-
param.typeDescriptions?.typeString !== undefined &&
|
|
618
|
-
param.typeDescriptions.typeString.startsWith("enum ")
|
|
619
|
-
);
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
function isElementaryType(param: any) {
|
|
623
|
-
return (
|
|
624
|
-
param.type === "ElementaryTypeName" ||
|
|
625
|
-
param.nodeType === "ElementaryTypeName"
|
|
626
|
-
);
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
function toCanonicalAbiType(type: string): string {
|
|
630
|
-
if (type.startsWith("int[")) {
|
|
631
|
-
return `int256${type.slice(3)}`;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
if (type === "int") {
|
|
635
|
-
return "int256";
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
if (type.startsWith("uint[")) {
|
|
639
|
-
return `uint256${type.slice(4)}`;
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
if (type === "uint") {
|
|
643
|
-
return "uint256";
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
if (type.startsWith("fixed[")) {
|
|
647
|
-
return `fixed128x128${type.slice(5)}`;
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
if (type === "fixed") {
|
|
651
|
-
return "fixed128x128";
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
if (type.startsWith("ufixed[")) {
|
|
655
|
-
return `ufixed128x128${type.slice(6)}`;
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
if (type === "ufixed") {
|
|
659
|
-
return "ufixed128x128";
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
return type;
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
function correctSelectors(
|
|
666
|
-
bytecodes: Bytecode[],
|
|
667
|
-
compilerOutput: CompilerOutput
|
|
668
|
-
) {
|
|
669
|
-
for (const bytecode of bytecodes) {
|
|
670
|
-
if (bytecode.isDeployment) {
|
|
671
|
-
continue;
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
const contract = bytecode.contract;
|
|
675
|
-
const methodIdentifiers =
|
|
676
|
-
compilerOutput.contracts[contract.location.file.sourceName][contract.name]
|
|
677
|
-
.evm.methodIdentifiers;
|
|
678
|
-
|
|
679
|
-
for (const [signature, hexSelector] of Object.entries(methodIdentifiers)) {
|
|
680
|
-
const functionName = signature.slice(0, signature.indexOf("("));
|
|
681
|
-
const selector = Buffer.from(hexSelector, "hex");
|
|
682
|
-
|
|
683
|
-
const contractFunction = contract.getFunctionFromSelector(selector);
|
|
684
|
-
|
|
685
|
-
if (contractFunction !== undefined) {
|
|
686
|
-
continue;
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
const fixedSelector = contract.correctSelector(functionName, selector);
|
|
690
|
-
|
|
691
|
-
if (!fixedSelector) {
|
|
692
|
-
// eslint-disable-next-line @nomicfoundation/hardhat-internal-rules/only-hardhat-error
|
|
693
|
-
throw new Error(
|
|
694
|
-
`Failed to compute the selector one or more implementations of ${contract.name}#${functionName}. Hardhat Network can automatically fix this problem if you don't use function overloading.`
|
|
695
|
-
);
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
}
|
|
7
|
+
export { createModelsAndDecodeBytecodes };
|