@qevm/abi 5.7.2 → 5.7.3
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/README.md +3 -4
- package/lib/_version.d.ts +1 -1
- package/lib/_version.js +1 -1
- package/lib/abi-coder.d.ts.map +1 -1
- package/lib/abi-coder.js +54 -54
- package/lib/abi-coder.js.map +1 -1
- package/lib/coders/abstract-coder.d.ts.map +1 -1
- package/lib/coders/abstract-coder.js +75 -84
- package/lib/coders/abstract-coder.js.map +1 -1
- package/lib/coders/address.d.ts.map +1 -1
- package/lib/coders/address.js +15 -32
- package/lib/coders/address.js.map +1 -1
- package/lib/coders/anonymous.js +12 -30
- package/lib/coders/anonymous.js.map +1 -1
- package/lib/coders/array.d.ts.map +1 -1
- package/lib/coders/array.js +71 -87
- package/lib/coders/array.js.map +1 -1
- package/lib/coders/boolean.d.ts.map +1 -1
- package/lib/coders/boolean.js +11 -28
- package/lib/coders/boolean.js.map +1 -1
- package/lib/coders/bytes.js +20 -39
- package/lib/coders/bytes.js.map +1 -1
- package/lib/coders/fixed-bytes.d.ts.map +1 -1
- package/lib/coders/fixed-bytes.js +16 -35
- package/lib/coders/fixed-bytes.js.map +1 -1
- package/lib/coders/function.d.ts +8 -0
- package/lib/coders/function.d.ts.map +1 -0
- package/lib/coders/function.js +46 -0
- package/lib/coders/function.js.map +1 -0
- package/lib/coders/null.d.ts.map +1 -1
- package/lib/coders/null.js +11 -28
- package/lib/coders/null.js.map +1 -1
- package/lib/coders/number.js +20 -39
- package/lib/coders/number.js.map +1 -1
- package/lib/coders/string.d.ts.map +1 -1
- package/lib/coders/string.js +14 -31
- package/lib/coders/string.js.map +1 -1
- package/lib/coders/tuple.d.ts.map +1 -1
- package/lib/coders/tuple.js +23 -42
- package/lib/coders/tuple.js.map +1 -1
- package/lib/fragments.d.ts.map +1 -1
- package/lib/fragments.js +256 -231
- package/lib/fragments.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -3
- package/lib/index.js.map +1 -1
- package/lib/interface.d.ts +1 -1
- package/lib/interface.d.ts.map +1 -1
- package/lib/interface.js +240 -247
- package/lib/interface.js.map +1 -1
- package/package.json +35 -31
- package/src.ts/_version.ts +1 -1
- package/src.ts/abi-coder.ts +64 -26
- package/src.ts/coders/abstract-coder.ts +78 -33
- package/src.ts/coders/address.ts +3 -5
- package/src.ts/coders/array.ts +90 -47
- package/src.ts/coders/boolean.ts +1 -3
- package/src.ts/coders/bytes.ts +1 -3
- package/src.ts/coders/fixed-bytes.ts +7 -2
- package/src.ts/coders/function.ts +64 -0
- package/src.ts/coders/null.ts +4 -3
- package/src.ts/coders/number.ts +1 -2
- package/src.ts/coders/string.ts +0 -1
- package/src.ts/coders/tuple.ts +31 -16
- package/src.ts/fragments.ts +411 -178
- package/src.ts/index.ts +20 -8
- package/src.ts/interface.ts +405 -153
package/src.ts/fragments.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { BigNumber } from "@qevm/bignumber";
|
|
4
|
-
import { defineReadOnly } from "@
|
|
4
|
+
import { defineReadOnly } from "@qevm/properties";
|
|
5
5
|
|
|
6
|
-
import { Logger } from "@
|
|
6
|
+
import { Logger } from "@qevm/logger";
|
|
7
7
|
import { version } from "./_version";
|
|
8
8
|
const logger = new Logger(version);
|
|
9
9
|
|
|
@@ -29,38 +29,51 @@ export interface JsonFragment {
|
|
|
29
29
|
readonly outputs?: ReadonlyArray<JsonFragmentType>;
|
|
30
30
|
|
|
31
31
|
readonly gas?: string;
|
|
32
|
-
}
|
|
32
|
+
}
|
|
33
33
|
|
|
34
|
-
const _constructorGuard = {
|
|
34
|
+
const _constructorGuard = {};
|
|
35
35
|
|
|
36
36
|
// AST Node parser state
|
|
37
37
|
type ParseState = {
|
|
38
|
-
allowArray?: boolean
|
|
39
|
-
allowName?: boolean
|
|
40
|
-
allowParams?: boolean
|
|
41
|
-
allowType?: boolean
|
|
42
|
-
readArray?: boolean
|
|
38
|
+
allowArray?: boolean;
|
|
39
|
+
allowName?: boolean;
|
|
40
|
+
allowParams?: boolean;
|
|
41
|
+
allowType?: boolean;
|
|
42
|
+
readArray?: boolean;
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
// AST Node
|
|
46
46
|
type ParseNode = {
|
|
47
|
-
parent?: any
|
|
48
|
-
type?: string
|
|
49
|
-
name?: string
|
|
50
|
-
state?: ParseState
|
|
51
|
-
indexed?: boolean
|
|
52
|
-
components?: Array<ParseNode
|
|
47
|
+
parent?: any;
|
|
48
|
+
type?: string;
|
|
49
|
+
name?: string;
|
|
50
|
+
state?: ParseState;
|
|
51
|
+
indexed?: boolean;
|
|
52
|
+
components?: Array<ParseNode>;
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
-
let ModifiersBytes: { [
|
|
56
|
-
|
|
55
|
+
let ModifiersBytes: { [name: string]: boolean } = {
|
|
56
|
+
calldata: true,
|
|
57
|
+
memory: true,
|
|
58
|
+
storage: true,
|
|
59
|
+
};
|
|
60
|
+
let ModifiersNest: { [name: string]: boolean } = {
|
|
61
|
+
calldata: true,
|
|
62
|
+
memory: true,
|
|
63
|
+
};
|
|
57
64
|
function checkModifier(type: string, name: string): boolean {
|
|
58
65
|
if (type === "bytes" || type === "string") {
|
|
59
|
-
if (ModifiersBytes[name]) {
|
|
66
|
+
if (ModifiersBytes[name]) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
60
69
|
} else if (type === "address") {
|
|
61
|
-
if (name === "payable") {
|
|
70
|
+
if (name === "payable") {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
62
73
|
} else if (type.indexOf("[") >= 0 || type === "tuple") {
|
|
63
|
-
if (ModifiersNest[name]) {
|
|
74
|
+
if (ModifiersNest[name]) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
64
77
|
}
|
|
65
78
|
if (ModifiersBytes[name] || name === "payable") {
|
|
66
79
|
logger.throwArgumentError("invalid modifier", "name", name);
|
|
@@ -70,17 +83,27 @@ function checkModifier(type: string, name: string): boolean {
|
|
|
70
83
|
|
|
71
84
|
// @TODO: Make sure that children of an indexed tuple are marked with a null indexed
|
|
72
85
|
function parseParamType(param: string, allowIndexed: boolean): ParseNode {
|
|
73
|
-
|
|
74
86
|
let originalParam = param;
|
|
75
87
|
function throwError(i: number) {
|
|
76
|
-
logger.throwArgumentError(
|
|
88
|
+
logger.throwArgumentError(
|
|
89
|
+
`unexpected character at position ${i}`,
|
|
90
|
+
"param",
|
|
91
|
+
param,
|
|
92
|
+
);
|
|
77
93
|
}
|
|
78
94
|
param = param.replace(/\s/g, " ");
|
|
79
95
|
|
|
80
96
|
function newNode(parent: ParseNode): ParseNode {
|
|
81
|
-
let node: ParseNode = {
|
|
82
|
-
|
|
83
|
-
|
|
97
|
+
let node: ParseNode = {
|
|
98
|
+
type: "",
|
|
99
|
+
name: "",
|
|
100
|
+
parent: parent,
|
|
101
|
+
state: { allowType: true },
|
|
102
|
+
};
|
|
103
|
+
if (allowIndexed) {
|
|
104
|
+
node.indexed = false;
|
|
105
|
+
}
|
|
106
|
+
return node;
|
|
84
107
|
}
|
|
85
108
|
|
|
86
109
|
let parent: ParseNode = { type: "", name: "", state: { allowType: true } };
|
|
@@ -97,7 +120,7 @@ function parseParamType(param: string, allowIndexed: boolean): ParseNode {
|
|
|
97
120
|
}
|
|
98
121
|
node.state.allowType = false;
|
|
99
122
|
node.type = verifyType(node.type);
|
|
100
|
-
node.components = [
|
|
123
|
+
node.components = [newNode(node)];
|
|
101
124
|
node = node.components[0];
|
|
102
125
|
break;
|
|
103
126
|
|
|
@@ -105,18 +128,24 @@ function parseParamType(param: string, allowIndexed: boolean): ParseNode {
|
|
|
105
128
|
delete node.state;
|
|
106
129
|
|
|
107
130
|
if (node.name === "indexed") {
|
|
108
|
-
if (!allowIndexed) {
|
|
131
|
+
if (!allowIndexed) {
|
|
132
|
+
throwError(i);
|
|
133
|
+
}
|
|
109
134
|
node.indexed = true;
|
|
110
135
|
node.name = "";
|
|
111
136
|
}
|
|
112
137
|
|
|
113
|
-
if (checkModifier(node.type, node.name)) {
|
|
138
|
+
if (checkModifier(node.type, node.name)) {
|
|
139
|
+
node.name = "";
|
|
140
|
+
}
|
|
114
141
|
|
|
115
142
|
node.type = verifyType(node.type);
|
|
116
143
|
|
|
117
144
|
let child = node;
|
|
118
145
|
node = node.parent;
|
|
119
|
-
if (!node) {
|
|
146
|
+
if (!node) {
|
|
147
|
+
throwError(i);
|
|
148
|
+
}
|
|
120
149
|
delete child.parent;
|
|
121
150
|
node.state.allowParams = false;
|
|
122
151
|
node.state.allowName = true;
|
|
@@ -127,17 +156,21 @@ function parseParamType(param: string, allowIndexed: boolean): ParseNode {
|
|
|
127
156
|
delete node.state;
|
|
128
157
|
|
|
129
158
|
if (node.name === "indexed") {
|
|
130
|
-
if (!allowIndexed) {
|
|
159
|
+
if (!allowIndexed) {
|
|
160
|
+
throwError(i);
|
|
161
|
+
}
|
|
131
162
|
node.indexed = true;
|
|
132
163
|
node.name = "";
|
|
133
164
|
}
|
|
134
165
|
|
|
135
|
-
if (checkModifier(node.type, node.name)) {
|
|
166
|
+
if (checkModifier(node.type, node.name)) {
|
|
167
|
+
node.name = "";
|
|
168
|
+
}
|
|
136
169
|
|
|
137
170
|
node.type = verifyType(node.type);
|
|
138
171
|
|
|
139
172
|
let sibling: ParseNode = newNode(node.parent);
|
|
140
|
-
|
|
173
|
+
//{ type: "", name: "", parent: node.parent, state: { allowType: true } };
|
|
141
174
|
node.parent.components.push(sibling);
|
|
142
175
|
delete node.parent;
|
|
143
176
|
node = sibling;
|
|
@@ -145,7 +178,6 @@ function parseParamType(param: string, allowIndexed: boolean): ParseNode {
|
|
|
145
178
|
|
|
146
179
|
// Hit a space...
|
|
147
180
|
case " ":
|
|
148
|
-
|
|
149
181
|
// If reading type, the type is done and may read a param or name
|
|
150
182
|
if (node.state.allowType) {
|
|
151
183
|
if (node.type !== "") {
|
|
@@ -160,8 +192,12 @@ function parseParamType(param: string, allowIndexed: boolean): ParseNode {
|
|
|
160
192
|
if (node.state.allowName) {
|
|
161
193
|
if (node.name !== "") {
|
|
162
194
|
if (node.name === "indexed") {
|
|
163
|
-
if (!allowIndexed) {
|
|
164
|
-
|
|
195
|
+
if (!allowIndexed) {
|
|
196
|
+
throwError(i);
|
|
197
|
+
}
|
|
198
|
+
if (node.indexed) {
|
|
199
|
+
throwError(i);
|
|
200
|
+
}
|
|
165
201
|
node.indexed = true;
|
|
166
202
|
node.name = "";
|
|
167
203
|
} else if (checkModifier(node.type, node.name)) {
|
|
@@ -175,7 +211,9 @@ function parseParamType(param: string, allowIndexed: boolean): ParseNode {
|
|
|
175
211
|
break;
|
|
176
212
|
|
|
177
213
|
case "[":
|
|
178
|
-
if (!node.state.allowArray) {
|
|
214
|
+
if (!node.state.allowArray) {
|
|
215
|
+
throwError(i);
|
|
216
|
+
}
|
|
179
217
|
|
|
180
218
|
node.type += c;
|
|
181
219
|
|
|
@@ -185,7 +223,9 @@ function parseParamType(param: string, allowIndexed: boolean): ParseNode {
|
|
|
185
223
|
break;
|
|
186
224
|
|
|
187
225
|
case "]":
|
|
188
|
-
if (!node.state.readArray) {
|
|
226
|
+
if (!node.state.readArray) {
|
|
227
|
+
throwError(i);
|
|
228
|
+
}
|
|
189
229
|
|
|
190
230
|
node.type += c;
|
|
191
231
|
|
|
@@ -206,17 +246,23 @@ function parseParamType(param: string, allowIndexed: boolean): ParseNode {
|
|
|
206
246
|
node.type += c;
|
|
207
247
|
} else {
|
|
208
248
|
throwError(i);
|
|
209
|
-
|
|
249
|
+
}
|
|
210
250
|
}
|
|
211
251
|
}
|
|
212
252
|
|
|
213
|
-
if (node.parent) {
|
|
253
|
+
if (node.parent) {
|
|
254
|
+
logger.throwArgumentError("unexpected eof", "param", param);
|
|
255
|
+
}
|
|
214
256
|
|
|
215
257
|
delete parent.state;
|
|
216
258
|
|
|
217
259
|
if (node.name === "indexed") {
|
|
218
|
-
if (!allowIndexed) {
|
|
219
|
-
|
|
260
|
+
if (!allowIndexed) {
|
|
261
|
+
throwError(originalParam.length - 7);
|
|
262
|
+
}
|
|
263
|
+
if (node.indexed) {
|
|
264
|
+
throwError(originalParam.length - 7);
|
|
265
|
+
}
|
|
220
266
|
node.indexed = true;
|
|
221
267
|
node.name = "";
|
|
222
268
|
} else if (checkModifier(node.type, node.name)) {
|
|
@@ -229,10 +275,12 @@ function parseParamType(param: string, allowIndexed: boolean): ParseNode {
|
|
|
229
275
|
}
|
|
230
276
|
|
|
231
277
|
function populate(object: any, params: any) {
|
|
232
|
-
for (let key in params) {
|
|
278
|
+
for (let key in params) {
|
|
279
|
+
defineReadOnly(object, key, params[key]);
|
|
280
|
+
}
|
|
233
281
|
}
|
|
234
282
|
|
|
235
|
-
export const FormatTypes: { [
|
|
283
|
+
export const FormatTypes: { [name: string]: string } = Object.freeze({
|
|
236
284
|
// Bare formatting, as is needed for computing a sighash of an event or function
|
|
237
285
|
sighash: "sighash",
|
|
238
286
|
|
|
@@ -243,13 +291,12 @@ export const FormatTypes: { [ name: string ]: string } = Object.freeze({
|
|
|
243
291
|
full: "full",
|
|
244
292
|
|
|
245
293
|
// JSON-format a la Solidity
|
|
246
|
-
json: "json"
|
|
294
|
+
json: "json",
|
|
247
295
|
});
|
|
248
296
|
|
|
249
297
|
const paramTypeArray = new RegExp(/^(.*)\[([0-9]*)\]$/);
|
|
250
298
|
|
|
251
299
|
export class ParamType {
|
|
252
|
-
|
|
253
300
|
// The local name of the parameter (of null if unbound)
|
|
254
301
|
readonly name: string;
|
|
255
302
|
|
|
@@ -275,9 +322,15 @@ export class ParamType {
|
|
|
275
322
|
readonly _isParamType: boolean;
|
|
276
323
|
|
|
277
324
|
constructor(constructorGuard: any, params: any) {
|
|
278
|
-
if (constructorGuard !== _constructorGuard) {
|
|
279
|
-
|
|
280
|
-
|
|
325
|
+
if (constructorGuard !== _constructorGuard) {
|
|
326
|
+
logger.throwError(
|
|
327
|
+
"use fromString",
|
|
328
|
+
Logger.errors.UNSUPPORTED_OPERATION,
|
|
329
|
+
{
|
|
330
|
+
operation: "new ParamType()",
|
|
331
|
+
},
|
|
332
|
+
);
|
|
333
|
+
}
|
|
281
334
|
populate(this, params);
|
|
282
335
|
|
|
283
336
|
let match = this.type.match(paramTypeArray);
|
|
@@ -286,15 +339,15 @@ export class ParamType {
|
|
|
286
339
|
arrayLength: parseInt(match[2] || "-1"),
|
|
287
340
|
arrayChildren: ParamType.fromObject({
|
|
288
341
|
type: match[1],
|
|
289
|
-
components: this.components
|
|
342
|
+
components: this.components,
|
|
290
343
|
}),
|
|
291
|
-
baseType: "array"
|
|
344
|
+
baseType: "array",
|
|
292
345
|
});
|
|
293
346
|
} else {
|
|
294
347
|
populate(this, {
|
|
295
348
|
arrayLength: null,
|
|
296
349
|
arrayChildren: null,
|
|
297
|
-
baseType:
|
|
350
|
+
baseType: this.components != null ? "tuple" : this.type,
|
|
298
351
|
});
|
|
299
352
|
}
|
|
300
353
|
|
|
@@ -308,19 +361,25 @@ export class ParamType {
|
|
|
308
361
|
// - minimal: "tuple(uint256,address) indexed"
|
|
309
362
|
// - full: "tuple(uint256 foo, address bar) indexed baz"
|
|
310
363
|
format(format?: string): string {
|
|
311
|
-
if (!format) {
|
|
364
|
+
if (!format) {
|
|
365
|
+
format = FormatTypes.sighash;
|
|
366
|
+
}
|
|
312
367
|
if (!FormatTypes[format]) {
|
|
313
368
|
logger.throwArgumentError("invalid format type", "format", format);
|
|
314
369
|
}
|
|
315
370
|
|
|
316
371
|
if (format === FormatTypes.json) {
|
|
317
372
|
let result: any = {
|
|
318
|
-
type:
|
|
319
|
-
name:
|
|
373
|
+
type: this.baseType === "tuple" ? "tuple" : this.type,
|
|
374
|
+
name: this.name || undefined,
|
|
320
375
|
};
|
|
321
|
-
if (typeof
|
|
376
|
+
if (typeof this.indexed === "boolean") {
|
|
377
|
+
result.indexed = this.indexed;
|
|
378
|
+
}
|
|
322
379
|
if (this.components) {
|
|
323
|
-
result.components = this.components.map((comp) =>
|
|
380
|
+
result.components = this.components.map((comp) =>
|
|
381
|
+
JSON.parse(comp.format(format)),
|
|
382
|
+
);
|
|
324
383
|
}
|
|
325
384
|
return JSON.stringify(result);
|
|
326
385
|
}
|
|
@@ -330,22 +389,30 @@ export class ParamType {
|
|
|
330
389
|
// Array
|
|
331
390
|
if (this.baseType === "array") {
|
|
332
391
|
result += this.arrayChildren.format(format);
|
|
333
|
-
result +=
|
|
392
|
+
result +=
|
|
393
|
+
"[" +
|
|
394
|
+
(this.arrayLength < 0 ? "" : String(this.arrayLength)) +
|
|
395
|
+
"]";
|
|
334
396
|
} else {
|
|
335
397
|
if (this.baseType === "tuple") {
|
|
336
398
|
if (format !== FormatTypes.sighash) {
|
|
337
399
|
result += this.type;
|
|
338
400
|
}
|
|
339
|
-
result +=
|
|
340
|
-
(
|
|
341
|
-
|
|
401
|
+
result +=
|
|
402
|
+
"(" +
|
|
403
|
+
this.components
|
|
404
|
+
.map((comp) => comp.format(format))
|
|
405
|
+
.join(format === FormatTypes.full ? ", " : ",") +
|
|
406
|
+
")";
|
|
342
407
|
} else {
|
|
343
408
|
result += this.type;
|
|
344
409
|
}
|
|
345
410
|
}
|
|
346
411
|
|
|
347
412
|
if (format !== FormatTypes.sighash) {
|
|
348
|
-
if (this.indexed === true) {
|
|
413
|
+
if (this.indexed === true) {
|
|
414
|
+
result += " indexed";
|
|
415
|
+
}
|
|
349
416
|
if (format === FormatTypes.full && this.name) {
|
|
350
417
|
result += " " + this.name;
|
|
351
418
|
}
|
|
@@ -354,21 +421,28 @@ export class ParamType {
|
|
|
354
421
|
return result;
|
|
355
422
|
}
|
|
356
423
|
|
|
357
|
-
static from(
|
|
358
|
-
|
|
424
|
+
static from(
|
|
425
|
+
value: string | JsonFragmentType | ParamType,
|
|
426
|
+
allowIndexed?: boolean,
|
|
427
|
+
): ParamType {
|
|
428
|
+
if (typeof value === "string") {
|
|
359
429
|
return ParamType.fromString(value, allowIndexed);
|
|
360
430
|
}
|
|
361
431
|
return ParamType.fromObject(value);
|
|
362
432
|
}
|
|
363
433
|
|
|
364
434
|
static fromObject(value: JsonFragmentType | ParamType): ParamType {
|
|
365
|
-
if (ParamType.isParamType(value)) {
|
|
435
|
+
if (ParamType.isParamType(value)) {
|
|
436
|
+
return value;
|
|
437
|
+
}
|
|
366
438
|
|
|
367
439
|
return new ParamType(_constructorGuard, {
|
|
368
|
-
name:
|
|
440
|
+
name: value.name || null,
|
|
369
441
|
type: verifyType(value.type),
|
|
370
|
-
indexed:
|
|
371
|
-
components:
|
|
442
|
+
indexed: value.indexed == null ? null : !!value.indexed,
|
|
443
|
+
components: value.components
|
|
444
|
+
? value.components.map(ParamType.fromObject)
|
|
445
|
+
: null,
|
|
372
446
|
});
|
|
373
447
|
}
|
|
374
448
|
|
|
@@ -378,7 +452,7 @@ export class ParamType {
|
|
|
378
452
|
name: node.name,
|
|
379
453
|
type: node.type,
|
|
380
454
|
indexed: node.indexed,
|
|
381
|
-
components: node.components
|
|
455
|
+
components: node.components,
|
|
382
456
|
});
|
|
383
457
|
}
|
|
384
458
|
|
|
@@ -388,13 +462,15 @@ export class ParamType {
|
|
|
388
462
|
static isParamType(value: any): value is ParamType {
|
|
389
463
|
return !!(value != null && value._isParamType);
|
|
390
464
|
}
|
|
391
|
-
}
|
|
465
|
+
}
|
|
392
466
|
|
|
393
467
|
function parseParams(value: string, allowIndex: boolean): Array<ParamType> {
|
|
394
|
-
return splitNesting(value).map((param) =>
|
|
468
|
+
return splitNesting(value).map((param) =>
|
|
469
|
+
ParamType.fromString(param, allowIndex),
|
|
470
|
+
);
|
|
395
471
|
}
|
|
396
472
|
|
|
397
|
-
type TypeCheck<T> = { -readonly [
|
|
473
|
+
type TypeCheck<T> = { -readonly [K in keyof T]: T[K] };
|
|
398
474
|
|
|
399
475
|
interface _Fragment {
|
|
400
476
|
readonly type: string;
|
|
@@ -403,7 +479,6 @@ interface _Fragment {
|
|
|
403
479
|
}
|
|
404
480
|
|
|
405
481
|
export abstract class Fragment {
|
|
406
|
-
|
|
407
482
|
readonly type: string;
|
|
408
483
|
readonly name: string;
|
|
409
484
|
readonly inputs: Array<ParamType>;
|
|
@@ -412,9 +487,13 @@ export abstract class Fragment {
|
|
|
412
487
|
|
|
413
488
|
constructor(constructorGuard: any, params: any) {
|
|
414
489
|
if (constructorGuard !== _constructorGuard) {
|
|
415
|
-
logger.throwError(
|
|
416
|
-
|
|
417
|
-
|
|
490
|
+
logger.throwError(
|
|
491
|
+
"use a static from method",
|
|
492
|
+
Logger.errors.UNSUPPORTED_OPERATION,
|
|
493
|
+
{
|
|
494
|
+
operation: "new Fragment()",
|
|
495
|
+
},
|
|
496
|
+
);
|
|
418
497
|
}
|
|
419
498
|
populate(this, params);
|
|
420
499
|
|
|
@@ -426,9 +505,11 @@ export abstract class Fragment {
|
|
|
426
505
|
abstract format(format?: string): string;
|
|
427
506
|
|
|
428
507
|
static from(value: Fragment | JsonFragment | string): Fragment {
|
|
429
|
-
if (Fragment.isFragment(value)) {
|
|
508
|
+
if (Fragment.isFragment(value)) {
|
|
509
|
+
return value;
|
|
510
|
+
}
|
|
430
511
|
|
|
431
|
-
if (typeof
|
|
512
|
+
if (typeof value === "string") {
|
|
432
513
|
return Fragment.fromString(value);
|
|
433
514
|
}
|
|
434
515
|
|
|
@@ -436,7 +517,9 @@ export abstract class Fragment {
|
|
|
436
517
|
}
|
|
437
518
|
|
|
438
519
|
static fromObject(value: Fragment | JsonFragment): Fragment {
|
|
439
|
-
if (Fragment.isFragment(value)) {
|
|
520
|
+
if (Fragment.isFragment(value)) {
|
|
521
|
+
return value;
|
|
522
|
+
}
|
|
440
523
|
|
|
441
524
|
switch (value.type) {
|
|
442
525
|
case "function":
|
|
@@ -453,26 +536,37 @@ export abstract class Fragment {
|
|
|
453
536
|
return null;
|
|
454
537
|
}
|
|
455
538
|
|
|
456
|
-
return logger.throwArgumentError(
|
|
539
|
+
return logger.throwArgumentError(
|
|
540
|
+
"invalid fragment object",
|
|
541
|
+
"value",
|
|
542
|
+
value,
|
|
543
|
+
);
|
|
457
544
|
}
|
|
458
545
|
|
|
459
546
|
static fromString(value: string): Fragment {
|
|
460
547
|
// Make sure the "returns" is surrounded by a space and all whitespace is exactly one space
|
|
461
548
|
value = value.replace(/\s/g, " ");
|
|
462
|
-
value = value
|
|
549
|
+
value = value
|
|
550
|
+
.replace(/\(/g, " (")
|
|
551
|
+
.replace(/\)/g, ") ")
|
|
552
|
+
.replace(/\s+/g, " ");
|
|
463
553
|
value = value.trim();
|
|
464
554
|
|
|
465
555
|
if (value.split(" ")[0] === "event") {
|
|
466
|
-
|
|
556
|
+
return EventFragment.fromString(value.substring(5).trim());
|
|
467
557
|
} else if (value.split(" ")[0] === "function") {
|
|
468
558
|
return FunctionFragment.fromString(value.substring(8).trim());
|
|
469
559
|
} else if (value.split("(")[0].trim() === "constructor") {
|
|
470
560
|
return ConstructorFragment.fromString(value.trim());
|
|
471
561
|
} else if (value.split(" ")[0] === "error") {
|
|
472
|
-
|
|
562
|
+
return ErrorFragment.fromString(value.substring(5).trim());
|
|
473
563
|
}
|
|
474
564
|
|
|
475
|
-
return logger.throwArgumentError(
|
|
565
|
+
return logger.throwArgumentError(
|
|
566
|
+
"unsupported fragment",
|
|
567
|
+
"value",
|
|
568
|
+
value,
|
|
569
|
+
);
|
|
476
570
|
}
|
|
477
571
|
|
|
478
572
|
static isFragment(value: any): value is Fragment {
|
|
@@ -488,7 +582,9 @@ export class EventFragment extends Fragment {
|
|
|
488
582
|
readonly anonymous: boolean;
|
|
489
583
|
|
|
490
584
|
format(format?: string): string {
|
|
491
|
-
if (!format) {
|
|
585
|
+
if (!format) {
|
|
586
|
+
format = FormatTypes.sighash;
|
|
587
|
+
}
|
|
492
588
|
if (!FormatTypes[format]) {
|
|
493
589
|
logger.throwArgumentError("invalid format type", "format", format);
|
|
494
590
|
}
|
|
@@ -498,7 +594,9 @@ export class EventFragment extends Fragment {
|
|
|
498
594
|
type: "event",
|
|
499
595
|
anonymous: this.anonymous,
|
|
500
596
|
name: this.name,
|
|
501
|
-
inputs: this.inputs.map((input) =>
|
|
597
|
+
inputs: this.inputs.map((input) =>
|
|
598
|
+
JSON.parse(input.format(format)),
|
|
599
|
+
),
|
|
502
600
|
});
|
|
503
601
|
}
|
|
504
602
|
|
|
@@ -508,9 +606,13 @@ export class EventFragment extends Fragment {
|
|
|
508
606
|
result += "event ";
|
|
509
607
|
}
|
|
510
608
|
|
|
511
|
-
result +=
|
|
512
|
-
|
|
513
|
-
|
|
609
|
+
result +=
|
|
610
|
+
this.name +
|
|
611
|
+
"(" +
|
|
612
|
+
this.inputs
|
|
613
|
+
.map((input) => input.format(format))
|
|
614
|
+
.join(format === FormatTypes.full ? ", " : ",") +
|
|
615
|
+
") ";
|
|
514
616
|
|
|
515
617
|
if (format !== FormatTypes.sighash) {
|
|
516
618
|
if (this.anonymous) {
|
|
@@ -522,14 +624,16 @@ export class EventFragment extends Fragment {
|
|
|
522
624
|
}
|
|
523
625
|
|
|
524
626
|
static from(value: EventFragment | JsonFragment | string): EventFragment {
|
|
525
|
-
if (typeof
|
|
627
|
+
if (typeof value === "string") {
|
|
526
628
|
return EventFragment.fromString(value);
|
|
527
629
|
}
|
|
528
630
|
return EventFragment.fromObject(value);
|
|
529
631
|
}
|
|
530
632
|
|
|
531
633
|
static fromObject(value: JsonFragment | EventFragment): EventFragment {
|
|
532
|
-
if (EventFragment.isEventFragment(value)) {
|
|
634
|
+
if (EventFragment.isEventFragment(value)) {
|
|
635
|
+
return value;
|
|
636
|
+
}
|
|
533
637
|
|
|
534
638
|
if (value.type !== "event") {
|
|
535
639
|
logger.throwArgumentError("invalid event object", "value", value);
|
|
@@ -538,15 +642,14 @@ export class EventFragment extends Fragment {
|
|
|
538
642
|
const params: TypeCheck<_EventFragment> = {
|
|
539
643
|
name: verifyIdentifier(value.name),
|
|
540
644
|
anonymous: value.anonymous,
|
|
541
|
-
inputs:
|
|
542
|
-
type: "event"
|
|
645
|
+
inputs: value.inputs ? value.inputs.map(ParamType.fromObject) : [],
|
|
646
|
+
type: "event",
|
|
543
647
|
};
|
|
544
648
|
|
|
545
649
|
return new EventFragment(_constructorGuard, params);
|
|
546
650
|
}
|
|
547
651
|
|
|
548
652
|
static fromString(value: string): EventFragment {
|
|
549
|
-
|
|
550
653
|
let match = value.match(regexParen);
|
|
551
654
|
if (!match) {
|
|
552
655
|
logger.throwArgumentError("invalid event string", "value", value);
|
|
@@ -554,7 +657,7 @@ export class EventFragment extends Fragment {
|
|
|
554
657
|
|
|
555
658
|
let anonymous = false;
|
|
556
659
|
match[3].split(" ").forEach((modifier) => {
|
|
557
|
-
switch(modifier.trim()) {
|
|
660
|
+
switch (modifier.trim()) {
|
|
558
661
|
case "anonymous":
|
|
559
662
|
anonymous = true;
|
|
560
663
|
break;
|
|
@@ -569,12 +672,12 @@ export class EventFragment extends Fragment {
|
|
|
569
672
|
name: match[1].trim(),
|
|
570
673
|
anonymous: anonymous,
|
|
571
674
|
inputs: parseParams(match[2], true),
|
|
572
|
-
type: "event"
|
|
675
|
+
type: "event",
|
|
573
676
|
});
|
|
574
677
|
}
|
|
575
678
|
|
|
576
679
|
static isEventFragment(value: any): value is EventFragment {
|
|
577
|
-
return
|
|
680
|
+
return value && value._isFragment && value.type === "event";
|
|
578
681
|
}
|
|
579
682
|
}
|
|
580
683
|
|
|
@@ -584,10 +687,18 @@ function parseGas(value: string, params: any): string {
|
|
|
584
687
|
let comps = value.split("@");
|
|
585
688
|
if (comps.length !== 1) {
|
|
586
689
|
if (comps.length > 2) {
|
|
587
|
-
logger.throwArgumentError(
|
|
690
|
+
logger.throwArgumentError(
|
|
691
|
+
"invalid human-readable ABI signature",
|
|
692
|
+
"value",
|
|
693
|
+
value,
|
|
694
|
+
);
|
|
588
695
|
}
|
|
589
696
|
if (!comps[1].match(/^[0-9]+$/)) {
|
|
590
|
-
logger.throwArgumentError(
|
|
697
|
+
logger.throwArgumentError(
|
|
698
|
+
"invalid human-readable ABI signature gas",
|
|
699
|
+
"value",
|
|
700
|
+
value,
|
|
701
|
+
);
|
|
591
702
|
}
|
|
592
703
|
params.gas = BigNumber.from(comps[1]);
|
|
593
704
|
return comps[0];
|
|
@@ -649,34 +760,53 @@ function verifyState(value: StateInputValue): StateOutputValue {
|
|
|
649
760
|
let result: any = {
|
|
650
761
|
constant: false,
|
|
651
762
|
payable: true,
|
|
652
|
-
stateMutability: "payable"
|
|
763
|
+
stateMutability: "payable",
|
|
653
764
|
};
|
|
654
765
|
|
|
655
766
|
if (value.stateMutability != null) {
|
|
656
767
|
result.stateMutability = value.stateMutability;
|
|
657
768
|
|
|
658
769
|
// Set (and check things are consistent) the constant property
|
|
659
|
-
result.constant =
|
|
770
|
+
result.constant =
|
|
771
|
+
result.stateMutability === "view" ||
|
|
772
|
+
result.stateMutability === "pure";
|
|
660
773
|
if (value.constant != null) {
|
|
661
|
-
if (
|
|
662
|
-
logger.throwArgumentError(
|
|
774
|
+
if (!!value.constant !== result.constant) {
|
|
775
|
+
logger.throwArgumentError(
|
|
776
|
+
"cannot have constant function with mutability " +
|
|
777
|
+
result.stateMutability,
|
|
778
|
+
"value",
|
|
779
|
+
value,
|
|
780
|
+
);
|
|
663
781
|
}
|
|
664
782
|
}
|
|
665
783
|
|
|
666
784
|
// Set (and check things are consistent) the payable property
|
|
667
|
-
result.payable =
|
|
785
|
+
result.payable = result.stateMutability === "payable";
|
|
668
786
|
if (value.payable != null) {
|
|
669
|
-
if (
|
|
670
|
-
logger.throwArgumentError(
|
|
787
|
+
if (!!value.payable !== result.payable) {
|
|
788
|
+
logger.throwArgumentError(
|
|
789
|
+
"cannot have payable function with mutability " +
|
|
790
|
+
result.stateMutability,
|
|
791
|
+
"value",
|
|
792
|
+
value,
|
|
793
|
+
);
|
|
671
794
|
}
|
|
672
795
|
}
|
|
673
|
-
|
|
674
796
|
} else if (value.payable != null) {
|
|
675
797
|
result.payable = !!value.payable;
|
|
676
798
|
|
|
677
799
|
// If payable we can assume non-constant; otherwise we can't assume
|
|
678
|
-
if (
|
|
679
|
-
|
|
800
|
+
if (
|
|
801
|
+
value.constant == null &&
|
|
802
|
+
!result.payable &&
|
|
803
|
+
value.type !== "constructor"
|
|
804
|
+
) {
|
|
805
|
+
logger.throwArgumentError(
|
|
806
|
+
"unable to determine stateMutability",
|
|
807
|
+
"value",
|
|
808
|
+
value,
|
|
809
|
+
);
|
|
680
810
|
}
|
|
681
811
|
|
|
682
812
|
result.constant = !!value.constant;
|
|
@@ -684,20 +814,26 @@ function verifyState(value: StateInputValue): StateOutputValue {
|
|
|
684
814
|
if (result.constant) {
|
|
685
815
|
result.stateMutability = "view";
|
|
686
816
|
} else {
|
|
687
|
-
result.stateMutability =
|
|
817
|
+
result.stateMutability = result.payable ? "payable" : "nonpayable";
|
|
688
818
|
}
|
|
689
819
|
|
|
690
820
|
if (result.payable && result.constant) {
|
|
691
|
-
logger.throwArgumentError(
|
|
821
|
+
logger.throwArgumentError(
|
|
822
|
+
"cannot have constant payable function",
|
|
823
|
+
"value",
|
|
824
|
+
value,
|
|
825
|
+
);
|
|
692
826
|
}
|
|
693
|
-
|
|
694
827
|
} else if (value.constant != null) {
|
|
695
828
|
result.constant = !!value.constant;
|
|
696
829
|
result.payable = !result.constant;
|
|
697
|
-
result.stateMutability =
|
|
698
|
-
|
|
830
|
+
result.stateMutability = result.constant ? "view" : "payable";
|
|
699
831
|
} else if (value.type !== "constructor") {
|
|
700
|
-
logger.throwArgumentError(
|
|
832
|
+
logger.throwArgumentError(
|
|
833
|
+
"unable to determine stateMutability",
|
|
834
|
+
"value",
|
|
835
|
+
value,
|
|
836
|
+
);
|
|
701
837
|
}
|
|
702
838
|
|
|
703
839
|
return result;
|
|
@@ -715,7 +851,9 @@ export class ConstructorFragment extends Fragment {
|
|
|
715
851
|
gas?: BigNumber;
|
|
716
852
|
|
|
717
853
|
format(format?: string): string {
|
|
718
|
-
if (!format) {
|
|
854
|
+
if (!format) {
|
|
855
|
+
format = FormatTypes.sighash;
|
|
856
|
+
}
|
|
719
857
|
if (!FormatTypes[format]) {
|
|
720
858
|
logger.throwArgumentError("invalid format type", "format", format);
|
|
721
859
|
}
|
|
@@ -723,22 +861,34 @@ export class ConstructorFragment extends Fragment {
|
|
|
723
861
|
if (format === FormatTypes.json) {
|
|
724
862
|
return JSON.stringify({
|
|
725
863
|
type: "constructor",
|
|
726
|
-
stateMutability:
|
|
864
|
+
stateMutability:
|
|
865
|
+
this.stateMutability !== "nonpayable"
|
|
866
|
+
? this.stateMutability
|
|
867
|
+
: undefined,
|
|
727
868
|
payable: this.payable,
|
|
728
|
-
gas:
|
|
729
|
-
inputs: this.inputs.map((input) =>
|
|
869
|
+
gas: this.gas ? this.gas.toNumber() : undefined,
|
|
870
|
+
inputs: this.inputs.map((input) =>
|
|
871
|
+
JSON.parse(input.format(format)),
|
|
872
|
+
),
|
|
730
873
|
});
|
|
731
874
|
}
|
|
732
875
|
|
|
733
876
|
if (format === FormatTypes.sighash) {
|
|
734
|
-
logger.throwError(
|
|
735
|
-
|
|
736
|
-
|
|
877
|
+
logger.throwError(
|
|
878
|
+
"cannot format a constructor for sighash",
|
|
879
|
+
Logger.errors.UNSUPPORTED_OPERATION,
|
|
880
|
+
{
|
|
881
|
+
operation: "format(sighash)",
|
|
882
|
+
},
|
|
883
|
+
);
|
|
737
884
|
}
|
|
738
885
|
|
|
739
|
-
let result =
|
|
740
|
-
(
|
|
741
|
-
|
|
886
|
+
let result =
|
|
887
|
+
"constructor(" +
|
|
888
|
+
this.inputs
|
|
889
|
+
.map((input) => input.format(format))
|
|
890
|
+
.join(format === FormatTypes.full ? ", " : ",") +
|
|
891
|
+
") ";
|
|
742
892
|
|
|
743
893
|
if (this.stateMutability && this.stateMutability !== "nonpayable") {
|
|
744
894
|
result += this.stateMutability + " ";
|
|
@@ -747,32 +897,46 @@ export class ConstructorFragment extends Fragment {
|
|
|
747
897
|
return result.trim();
|
|
748
898
|
}
|
|
749
899
|
|
|
750
|
-
static from(
|
|
751
|
-
|
|
900
|
+
static from(
|
|
901
|
+
value: ConstructorFragment | JsonFragment | string,
|
|
902
|
+
): ConstructorFragment {
|
|
903
|
+
if (typeof value === "string") {
|
|
752
904
|
return ConstructorFragment.fromString(value);
|
|
753
905
|
}
|
|
754
906
|
return ConstructorFragment.fromObject(value);
|
|
755
907
|
}
|
|
756
908
|
|
|
757
|
-
static fromObject(
|
|
758
|
-
|
|
909
|
+
static fromObject(
|
|
910
|
+
value: ConstructorFragment | JsonFragment,
|
|
911
|
+
): ConstructorFragment {
|
|
912
|
+
if (ConstructorFragment.isConstructorFragment(value)) {
|
|
913
|
+
return value;
|
|
914
|
+
}
|
|
759
915
|
|
|
760
916
|
if (value.type !== "constructor") {
|
|
761
|
-
logger.throwArgumentError(
|
|
917
|
+
logger.throwArgumentError(
|
|
918
|
+
"invalid constructor object",
|
|
919
|
+
"value",
|
|
920
|
+
value,
|
|
921
|
+
);
|
|
762
922
|
}
|
|
763
923
|
|
|
764
924
|
let state = verifyState(value);
|
|
765
925
|
if (state.constant) {
|
|
766
|
-
logger.throwArgumentError(
|
|
926
|
+
logger.throwArgumentError(
|
|
927
|
+
"constructor cannot be constant",
|
|
928
|
+
"value",
|
|
929
|
+
value,
|
|
930
|
+
);
|
|
767
931
|
}
|
|
768
932
|
|
|
769
933
|
const params: TypeCheck<_ConstructorFragment> = {
|
|
770
934
|
name: null,
|
|
771
935
|
type: value.type,
|
|
772
|
-
inputs:
|
|
936
|
+
inputs: value.inputs ? value.inputs.map(ParamType.fromObject) : [],
|
|
773
937
|
payable: state.payable,
|
|
774
938
|
stateMutability: state.stateMutability,
|
|
775
|
-
gas:
|
|
939
|
+
gas: value.gas ? BigNumber.from(value.gas) : null,
|
|
776
940
|
};
|
|
777
941
|
|
|
778
942
|
return new ConstructorFragment(_constructorGuard, params);
|
|
@@ -785,7 +949,11 @@ export class ConstructorFragment extends Fragment {
|
|
|
785
949
|
|
|
786
950
|
let parens = value.match(regexParen);
|
|
787
951
|
if (!parens || parens[1].trim() !== "constructor") {
|
|
788
|
-
logger.throwArgumentError(
|
|
952
|
+
logger.throwArgumentError(
|
|
953
|
+
"invalid constructor string",
|
|
954
|
+
"value",
|
|
955
|
+
value,
|
|
956
|
+
);
|
|
789
957
|
}
|
|
790
958
|
|
|
791
959
|
params.inputs = parseParams(parens[2].trim(), false);
|
|
@@ -796,7 +964,7 @@ export class ConstructorFragment extends Fragment {
|
|
|
796
964
|
}
|
|
797
965
|
|
|
798
966
|
static isConstructorFragment(value: any): value is ConstructorFragment {
|
|
799
|
-
return
|
|
967
|
+
return value && value._isFragment && value.type === "constructor";
|
|
800
968
|
}
|
|
801
969
|
}
|
|
802
970
|
|
|
@@ -810,7 +978,9 @@ export class FunctionFragment extends ConstructorFragment {
|
|
|
810
978
|
outputs?: Array<ParamType>;
|
|
811
979
|
|
|
812
980
|
format(format?: string): string {
|
|
813
|
-
if (!format) {
|
|
981
|
+
if (!format) {
|
|
982
|
+
format = FormatTypes.sighash;
|
|
983
|
+
}
|
|
814
984
|
if (!FormatTypes[format]) {
|
|
815
985
|
logger.throwArgumentError("invalid format type", "format", format);
|
|
816
986
|
}
|
|
@@ -820,11 +990,18 @@ export class FunctionFragment extends ConstructorFragment {
|
|
|
820
990
|
type: "function",
|
|
821
991
|
name: this.name,
|
|
822
992
|
constant: this.constant,
|
|
823
|
-
stateMutability:
|
|
993
|
+
stateMutability:
|
|
994
|
+
this.stateMutability !== "nonpayable"
|
|
995
|
+
? this.stateMutability
|
|
996
|
+
: undefined,
|
|
824
997
|
payable: this.payable,
|
|
825
|
-
gas:
|
|
826
|
-
inputs: this.inputs.map((input) =>
|
|
827
|
-
|
|
998
|
+
gas: this.gas ? this.gas.toNumber() : undefined,
|
|
999
|
+
inputs: this.inputs.map((input) =>
|
|
1000
|
+
JSON.parse(input.format(format)),
|
|
1001
|
+
),
|
|
1002
|
+
outputs: this.outputs.map((output) =>
|
|
1003
|
+
JSON.parse(output.format(format)),
|
|
1004
|
+
),
|
|
828
1005
|
});
|
|
829
1006
|
}
|
|
830
1007
|
|
|
@@ -834,23 +1011,30 @@ export class FunctionFragment extends ConstructorFragment {
|
|
|
834
1011
|
result += "function ";
|
|
835
1012
|
}
|
|
836
1013
|
|
|
837
|
-
result +=
|
|
838
|
-
|
|
839
|
-
|
|
1014
|
+
result +=
|
|
1015
|
+
this.name +
|
|
1016
|
+
"(" +
|
|
1017
|
+
this.inputs
|
|
1018
|
+
.map((input) => input.format(format))
|
|
1019
|
+
.join(format === FormatTypes.full ? ", " : ",") +
|
|
1020
|
+
") ";
|
|
840
1021
|
|
|
841
1022
|
if (format !== FormatTypes.sighash) {
|
|
842
1023
|
if (this.stateMutability) {
|
|
843
1024
|
if (this.stateMutability !== "nonpayable") {
|
|
844
|
-
result +=
|
|
1025
|
+
result += this.stateMutability + " ";
|
|
845
1026
|
}
|
|
846
1027
|
} else if (this.constant) {
|
|
847
1028
|
result += "view ";
|
|
848
1029
|
}
|
|
849
1030
|
|
|
850
1031
|
if (this.outputs && this.outputs.length) {
|
|
851
|
-
result +=
|
|
852
|
-
(
|
|
853
|
-
|
|
1032
|
+
result +=
|
|
1033
|
+
"returns (" +
|
|
1034
|
+
this.outputs
|
|
1035
|
+
.map((output) => output.format(format))
|
|
1036
|
+
.join(", ") +
|
|
1037
|
+
") ";
|
|
854
1038
|
}
|
|
855
1039
|
|
|
856
1040
|
if (this.gas != null) {
|
|
@@ -861,18 +1045,28 @@ export class FunctionFragment extends ConstructorFragment {
|
|
|
861
1045
|
return result.trim();
|
|
862
1046
|
}
|
|
863
1047
|
|
|
864
|
-
static from(
|
|
865
|
-
|
|
1048
|
+
static from(
|
|
1049
|
+
value: FunctionFragment | JsonFragment | string,
|
|
1050
|
+
): FunctionFragment {
|
|
1051
|
+
if (typeof value === "string") {
|
|
866
1052
|
return FunctionFragment.fromString(value);
|
|
867
1053
|
}
|
|
868
1054
|
return FunctionFragment.fromObject(value);
|
|
869
1055
|
}
|
|
870
1056
|
|
|
871
|
-
static fromObject(
|
|
872
|
-
|
|
1057
|
+
static fromObject(
|
|
1058
|
+
value: FunctionFragment | JsonFragment,
|
|
1059
|
+
): FunctionFragment {
|
|
1060
|
+
if (FunctionFragment.isFunctionFragment(value)) {
|
|
1061
|
+
return value;
|
|
1062
|
+
}
|
|
873
1063
|
|
|
874
1064
|
if (value.type !== "function") {
|
|
875
|
-
logger.throwArgumentError(
|
|
1065
|
+
logger.throwArgumentError(
|
|
1066
|
+
"invalid function object",
|
|
1067
|
+
"value",
|
|
1068
|
+
value,
|
|
1069
|
+
);
|
|
876
1070
|
}
|
|
877
1071
|
|
|
878
1072
|
let state = verifyState(value);
|
|
@@ -881,11 +1075,13 @@ export class FunctionFragment extends ConstructorFragment {
|
|
|
881
1075
|
type: value.type,
|
|
882
1076
|
name: verifyIdentifier(value.name),
|
|
883
1077
|
constant: state.constant,
|
|
884
|
-
inputs:
|
|
885
|
-
outputs:
|
|
1078
|
+
inputs: value.inputs ? value.inputs.map(ParamType.fromObject) : [],
|
|
1079
|
+
outputs: value.outputs
|
|
1080
|
+
? value.outputs.map(ParamType.fromObject)
|
|
1081
|
+
: [],
|
|
886
1082
|
payable: state.payable,
|
|
887
1083
|
stateMutability: state.stateMutability,
|
|
888
|
-
gas:
|
|
1084
|
+
gas: value.gas ? BigNumber.from(value.gas) : null,
|
|
889
1085
|
};
|
|
890
1086
|
|
|
891
1087
|
return new FunctionFragment(_constructorGuard, params);
|
|
@@ -897,16 +1093,26 @@ export class FunctionFragment extends ConstructorFragment {
|
|
|
897
1093
|
|
|
898
1094
|
let comps = value.split(" returns ");
|
|
899
1095
|
if (comps.length > 2) {
|
|
900
|
-
logger.throwArgumentError(
|
|
1096
|
+
logger.throwArgumentError(
|
|
1097
|
+
"invalid function string",
|
|
1098
|
+
"value",
|
|
1099
|
+
value,
|
|
1100
|
+
);
|
|
901
1101
|
}
|
|
902
1102
|
|
|
903
1103
|
let parens = comps[0].match(regexParen);
|
|
904
1104
|
if (!parens) {
|
|
905
|
-
logger.throwArgumentError(
|
|
1105
|
+
logger.throwArgumentError(
|
|
1106
|
+
"invalid function signature",
|
|
1107
|
+
"value",
|
|
1108
|
+
value,
|
|
1109
|
+
);
|
|
906
1110
|
}
|
|
907
1111
|
|
|
908
1112
|
params.name = parens[1].trim();
|
|
909
|
-
if (params.name) {
|
|
1113
|
+
if (params.name) {
|
|
1114
|
+
verifyIdentifier(params.name);
|
|
1115
|
+
}
|
|
910
1116
|
|
|
911
1117
|
params.inputs = parseParams(parens[2], false);
|
|
912
1118
|
|
|
@@ -914,20 +1120,20 @@ export class FunctionFragment extends ConstructorFragment {
|
|
|
914
1120
|
|
|
915
1121
|
// We have outputs
|
|
916
1122
|
if (comps.length > 1) {
|
|
917
|
-
|
|
1123
|
+
let returns = comps[1].match(regexParen);
|
|
918
1124
|
if (returns[1].trim() != "" || returns[3].trim() != "") {
|
|
919
1125
|
logger.throwArgumentError("unexpected tokens", "value", value);
|
|
920
1126
|
}
|
|
921
1127
|
params.outputs = parseParams(returns[2], false);
|
|
922
1128
|
} else {
|
|
923
|
-
params.outputs = [
|
|
1129
|
+
params.outputs = [];
|
|
924
1130
|
}
|
|
925
1131
|
|
|
926
1132
|
return FunctionFragment.fromObject(params);
|
|
927
1133
|
}
|
|
928
1134
|
|
|
929
1135
|
static isFunctionFragment(value: any): value is FunctionFragment {
|
|
930
|
-
return
|
|
1136
|
+
return value && value._isFragment && value.type === "function";
|
|
931
1137
|
}
|
|
932
1138
|
}
|
|
933
1139
|
|
|
@@ -937,15 +1143,20 @@ export class FunctionFragment extends ConstructorFragment {
|
|
|
937
1143
|
function checkForbidden(fragment: ErrorFragment): ErrorFragment {
|
|
938
1144
|
const sig = fragment.format();
|
|
939
1145
|
if (sig === "Error(string)" || sig === "Panic(uint256)") {
|
|
940
|
-
logger.throwArgumentError(
|
|
1146
|
+
logger.throwArgumentError(
|
|
1147
|
+
`cannot specify user defined ${sig} error`,
|
|
1148
|
+
"fragment",
|
|
1149
|
+
fragment,
|
|
1150
|
+
);
|
|
941
1151
|
}
|
|
942
1152
|
return fragment;
|
|
943
1153
|
}
|
|
944
1154
|
|
|
945
1155
|
export class ErrorFragment extends Fragment {
|
|
946
|
-
|
|
947
1156
|
format(format?: string): string {
|
|
948
|
-
if (!format) {
|
|
1157
|
+
if (!format) {
|
|
1158
|
+
format = FormatTypes.sighash;
|
|
1159
|
+
}
|
|
949
1160
|
if (!FormatTypes[format]) {
|
|
950
1161
|
logger.throwArgumentError("invalid format type", "format", format);
|
|
951
1162
|
}
|
|
@@ -954,7 +1165,9 @@ export class ErrorFragment extends Fragment {
|
|
|
954
1165
|
return JSON.stringify({
|
|
955
1166
|
type: "error",
|
|
956
1167
|
name: this.name,
|
|
957
|
-
inputs: this.inputs.map((input) =>
|
|
1168
|
+
inputs: this.inputs.map((input) =>
|
|
1169
|
+
JSON.parse(input.format(format)),
|
|
1170
|
+
),
|
|
958
1171
|
});
|
|
959
1172
|
}
|
|
960
1173
|
|
|
@@ -964,22 +1177,28 @@ export class ErrorFragment extends Fragment {
|
|
|
964
1177
|
result += "error ";
|
|
965
1178
|
}
|
|
966
1179
|
|
|
967
|
-
result +=
|
|
968
|
-
|
|
969
|
-
|
|
1180
|
+
result +=
|
|
1181
|
+
this.name +
|
|
1182
|
+
"(" +
|
|
1183
|
+
this.inputs
|
|
1184
|
+
.map((input) => input.format(format))
|
|
1185
|
+
.join(format === FormatTypes.full ? ", " : ",") +
|
|
1186
|
+
") ";
|
|
970
1187
|
|
|
971
1188
|
return result.trim();
|
|
972
1189
|
}
|
|
973
1190
|
|
|
974
1191
|
static from(value: ErrorFragment | JsonFragment | string): ErrorFragment {
|
|
975
|
-
if (typeof
|
|
1192
|
+
if (typeof value === "string") {
|
|
976
1193
|
return ErrorFragment.fromString(value);
|
|
977
1194
|
}
|
|
978
1195
|
return ErrorFragment.fromObject(value);
|
|
979
1196
|
}
|
|
980
1197
|
|
|
981
1198
|
static fromObject(value: ErrorFragment | JsonFragment): ErrorFragment {
|
|
982
|
-
if (ErrorFragment.isErrorFragment(value)) {
|
|
1199
|
+
if (ErrorFragment.isErrorFragment(value)) {
|
|
1200
|
+
return value;
|
|
1201
|
+
}
|
|
983
1202
|
|
|
984
1203
|
if (value.type !== "error") {
|
|
985
1204
|
logger.throwArgumentError("invalid error object", "value", value);
|
|
@@ -988,7 +1207,7 @@ export class ErrorFragment extends Fragment {
|
|
|
988
1207
|
const params: TypeCheck<_Fragment> = {
|
|
989
1208
|
type: value.type,
|
|
990
1209
|
name: verifyIdentifier(value.name),
|
|
991
|
-
inputs:
|
|
1210
|
+
inputs: value.inputs ? value.inputs.map(ParamType.fromObject) : [],
|
|
992
1211
|
};
|
|
993
1212
|
|
|
994
1213
|
return checkForbidden(new ErrorFragment(_constructorGuard, params));
|
|
@@ -999,11 +1218,17 @@ export class ErrorFragment extends Fragment {
|
|
|
999
1218
|
|
|
1000
1219
|
let parens = value.match(regexParen);
|
|
1001
1220
|
if (!parens) {
|
|
1002
|
-
logger.throwArgumentError(
|
|
1221
|
+
logger.throwArgumentError(
|
|
1222
|
+
"invalid error signature",
|
|
1223
|
+
"value",
|
|
1224
|
+
value,
|
|
1225
|
+
);
|
|
1003
1226
|
}
|
|
1004
1227
|
|
|
1005
1228
|
params.name = parens[1].trim();
|
|
1006
|
-
if (params.name) {
|
|
1229
|
+
if (params.name) {
|
|
1230
|
+
verifyIdentifier(params.name);
|
|
1231
|
+
}
|
|
1007
1232
|
|
|
1008
1233
|
params.inputs = parseParams(parens[2], false);
|
|
1009
1234
|
|
|
@@ -1011,12 +1236,11 @@ export class ErrorFragment extends Fragment {
|
|
|
1011
1236
|
}
|
|
1012
1237
|
|
|
1013
1238
|
static isErrorFragment(value: any): value is ErrorFragment {
|
|
1014
|
-
return
|
|
1239
|
+
return value && value._isFragment && value.type === "error";
|
|
1015
1240
|
}
|
|
1016
1241
|
}
|
|
1017
1242
|
|
|
1018
1243
|
function verifyType(type: string): string {
|
|
1019
|
-
|
|
1020
1244
|
// These need to be transformed to their full description
|
|
1021
1245
|
if (type.match(/^uint($|[^1-9])/)) {
|
|
1022
1246
|
type = "uint256" + type.substring(4);
|
|
@@ -1033,7 +1257,11 @@ function verifyType(type: string): string {
|
|
|
1033
1257
|
const regexIdentifier = new RegExp("^[a-zA-Z$_][a-zA-Z0-9$_]*$");
|
|
1034
1258
|
function verifyIdentifier(value: string): string {
|
|
1035
1259
|
if (!value || !value.match(regexIdentifier)) {
|
|
1036
|
-
logger.throwArgumentError(
|
|
1260
|
+
logger.throwArgumentError(
|
|
1261
|
+
`invalid identifier "${value}"`,
|
|
1262
|
+
"value",
|
|
1263
|
+
value,
|
|
1264
|
+
);
|
|
1037
1265
|
}
|
|
1038
1266
|
return value;
|
|
1039
1267
|
}
|
|
@@ -1058,13 +1286,18 @@ function splitNesting(value: string): Array<any> {
|
|
|
1058
1286
|
} else if (c === ")") {
|
|
1059
1287
|
depth--;
|
|
1060
1288
|
if (depth === -1) {
|
|
1061
|
-
logger.throwArgumentError(
|
|
1289
|
+
logger.throwArgumentError(
|
|
1290
|
+
"unbalanced parenthesis",
|
|
1291
|
+
"value",
|
|
1292
|
+
value,
|
|
1293
|
+
);
|
|
1062
1294
|
}
|
|
1063
1295
|
}
|
|
1064
1296
|
}
|
|
1065
1297
|
}
|
|
1066
|
-
if (accum) {
|
|
1298
|
+
if (accum) {
|
|
1299
|
+
result.push(accum);
|
|
1300
|
+
}
|
|
1067
1301
|
|
|
1068
1302
|
return result;
|
|
1069
1303
|
}
|
|
1070
|
-
|