@ethersproject/abi
Advanced tools
Comparing version 5.0.12 to 5.7.0
@@ -1,2 +0,2 @@ | ||
export declare const version = "abi/5.0.12"; | ||
export declare const version = "abi/5.7.0"; | ||
//# sourceMappingURL=_version.d.ts.map |
@@ -1,2 +0,2 @@ | ||
export const version = "abi/5.0.12"; | ||
export const version = "abi/5.7.0"; | ||
//# sourceMappingURL=_version.js.map |
@@ -12,7 +12,7 @@ import { BytesLike } from "@ethersproject/bytes"; | ||
_getWriter(): Writer; | ||
getDefaultValue(types: Array<string | ParamType>): Result; | ||
encode(types: Array<string | ParamType>, values: Array<any>): string; | ||
decode(types: Array<string | ParamType>, data: BytesLike, loose?: boolean): Result; | ||
getDefaultValue(types: ReadonlyArray<string | ParamType>): Result; | ||
encode(types: ReadonlyArray<string | ParamType>, values: ReadonlyArray<any>): string; | ||
decode(types: ReadonlyArray<string | ParamType>, data: BytesLike, loose?: boolean): Result; | ||
} | ||
export declare const defaultAbiCoder: AbiCoder; | ||
//# sourceMappingURL=abi-coder.d.ts.map |
@@ -23,3 +23,2 @@ "use strict"; | ||
constructor(coerceFunc) { | ||
logger.checkNew(new.target, AbiCoder); | ||
defineReadOnly(this, "coerceFunc", coerceFunc || null); | ||
@@ -26,0 +25,0 @@ } |
@@ -14,3 +14,3 @@ "use strict"; | ||
try { | ||
getAddress(value); | ||
value = getAddress(value); | ||
} | ||
@@ -17,0 +17,0 @@ catch (error) { |
@@ -134,2 +134,3 @@ "use strict"; | ||
Object.defineProperty(values, name, { | ||
enumerable: true, | ||
get: () => { throw value; } | ||
@@ -146,2 +147,3 @@ }); | ||
Object.defineProperty(values, i, { | ||
enumerable: true, | ||
get: () => { throw value; } | ||
@@ -190,2 +192,13 @@ }); | ||
count = reader.readValue().toNumber(); | ||
// Check that there is *roughly* enough data to ensure | ||
// stray random data is not being read as a length. Each | ||
// slot requires at least 32 bytes for their value (or 32 | ||
// bytes as a link to the data). This could use a much | ||
// tighter bound, but we are erroring on the side of safety. | ||
if (count * 32 > reader._data.length) { | ||
logger.throwError("insufficient data length", Logger.errors.BUFFER_OVERRUN, { | ||
length: reader._data.length, | ||
count: count | ||
}); | ||
} | ||
} | ||
@@ -192,0 +205,0 @@ let coders = []; |
import { BigNumber } from "@ethersproject/bignumber"; | ||
export interface JsonFragmentType { | ||
name?: string; | ||
indexed?: boolean; | ||
type?: string; | ||
components?: Array<JsonFragmentType>; | ||
readonly name?: string; | ||
readonly indexed?: boolean; | ||
readonly type?: string; | ||
readonly internalType?: any; | ||
readonly components?: ReadonlyArray<JsonFragmentType>; | ||
} | ||
export interface JsonFragment { | ||
name?: string; | ||
type?: string; | ||
anonymous?: boolean; | ||
payable?: boolean; | ||
constant?: boolean; | ||
stateMutability?: string; | ||
inputs?: Array<JsonFragmentType>; | ||
outputs?: Array<JsonFragmentType>; | ||
gas?: string; | ||
readonly name?: string; | ||
readonly type?: string; | ||
readonly anonymous?: boolean; | ||
readonly payable?: boolean; | ||
readonly constant?: boolean; | ||
readonly stateMutability?: string; | ||
readonly inputs?: ReadonlyArray<JsonFragmentType>; | ||
readonly outputs?: ReadonlyArray<JsonFragmentType>; | ||
readonly gas?: string; | ||
} | ||
@@ -77,2 +78,9 @@ export declare const FormatTypes: { | ||
} | ||
export declare class ErrorFragment extends Fragment { | ||
format(format?: string): string; | ||
static from(value: ErrorFragment | JsonFragment | string): ErrorFragment; | ||
static fromObject(value: ErrorFragment | JsonFragment): ErrorFragment; | ||
static fromString(value: string): ErrorFragment; | ||
static isErrorFragment(value: any): value is ErrorFragment; | ||
} | ||
//# sourceMappingURL=fragments.d.ts.map |
@@ -204,3 +204,3 @@ "use strict"; | ||
minimal: "minimal", | ||
// Human-Readble with nice spacing, including all names | ||
// Human-Readable with nice spacing, including all names | ||
full: "full", | ||
@@ -243,3 +243,3 @@ // JSON-format a la Solidity | ||
// - minimal: "tuple(uint256,address) indexed" | ||
// - full: "tuple(uint256 foo, addres bar) indexed baz" | ||
// - full: "tuple(uint256 foo, address bar) indexed baz" | ||
format(format) { | ||
@@ -359,2 +359,4 @@ if (!format) { | ||
return ConstructorFragment.fromObject(value); | ||
case "error": | ||
return ErrorFragment.fromObject(value); | ||
case "fallback": | ||
@@ -381,2 +383,5 @@ case "receive": | ||
} | ||
else if (value.split(" ")[0] === "error") { | ||
return ErrorFragment.fromString(value.substring(5).trim()); | ||
} | ||
return logger.throwArgumentError("unsupported fragment", "value", value); | ||
@@ -737,6 +742,70 @@ } | ||
} | ||
//export class ErrorFragment extends Fragment { | ||
//} | ||
//export class StructFragment extends Fragment { | ||
//} | ||
function checkForbidden(fragment) { | ||
const sig = fragment.format(); | ||
if (sig === "Error(string)" || sig === "Panic(uint256)") { | ||
logger.throwArgumentError(`cannot specify user defined ${sig} error`, "fragment", fragment); | ||
} | ||
return fragment; | ||
} | ||
export class ErrorFragment extends Fragment { | ||
format(format) { | ||
if (!format) { | ||
format = FormatTypes.sighash; | ||
} | ||
if (!FormatTypes[format]) { | ||
logger.throwArgumentError("invalid format type", "format", format); | ||
} | ||
if (format === FormatTypes.json) { | ||
return JSON.stringify({ | ||
type: "error", | ||
name: this.name, | ||
inputs: this.inputs.map((input) => JSON.parse(input.format(format))), | ||
}); | ||
} | ||
let result = ""; | ||
if (format !== FormatTypes.sighash) { | ||
result += "error "; | ||
} | ||
result += this.name + "(" + this.inputs.map((input) => input.format(format)).join((format === FormatTypes.full) ? ", " : ",") + ") "; | ||
return result.trim(); | ||
} | ||
static from(value) { | ||
if (typeof (value) === "string") { | ||
return ErrorFragment.fromString(value); | ||
} | ||
return ErrorFragment.fromObject(value); | ||
} | ||
static fromObject(value) { | ||
if (ErrorFragment.isErrorFragment(value)) { | ||
return value; | ||
} | ||
if (value.type !== "error") { | ||
logger.throwArgumentError("invalid error object", "value", value); | ||
} | ||
const params = { | ||
type: value.type, | ||
name: verifyIdentifier(value.name), | ||
inputs: (value.inputs ? value.inputs.map(ParamType.fromObject) : []) | ||
}; | ||
return checkForbidden(new ErrorFragment(_constructorGuard, params)); | ||
} | ||
static fromString(value) { | ||
let params = { type: "error" }; | ||
let parens = value.match(regexParen); | ||
if (!parens) { | ||
logger.throwArgumentError("invalid error signature", "value", value); | ||
} | ||
params.name = parens[1].trim(); | ||
if (params.name) { | ||
verifyIdentifier(params.name); | ||
} | ||
params.inputs = parseParams(parens[2], false); | ||
return checkForbidden(ErrorFragment.fromObject(params)); | ||
} | ||
static isErrorFragment(value) { | ||
return (value && value._isFragment && value.type === "error"); | ||
} | ||
} | ||
function verifyType(type) { | ||
@@ -753,3 +822,4 @@ // These need to be transformed to their full description | ||
} | ||
const regexIdentifier = new RegExp("^[A-Za-z_][A-Za-z0-9_]*$"); | ||
// See: https://github.com/ethereum/solidity/blob/1f8f1a3db93a548d0555e3e14cfc55a10e25b60e/docs/grammar/SolidityLexer.g4#L234 | ||
const regexIdentifier = new RegExp("^[a-zA-Z$_][a-zA-Z0-9$_]*$"); | ||
function verifyIdentifier(value) { | ||
@@ -756,0 +826,0 @@ if (!value || !value.match(regexIdentifier)) { |
@@ -1,5 +0,5 @@ | ||
import { ConstructorFragment, EventFragment, FormatTypes, Fragment, FunctionFragment, JsonFragment, JsonFragmentType, ParamType } from "./fragments"; | ||
import { ConstructorFragment, ErrorFragment, EventFragment, FormatTypes, Fragment, FunctionFragment, JsonFragment, JsonFragmentType, ParamType } from "./fragments"; | ||
import { AbiCoder, CoerceFunc, defaultAbiCoder } from "./abi-coder"; | ||
import { checkResultErrors, Indexed, Interface, LogDescription, Result, TransactionDescription } from "./interface"; | ||
export { ConstructorFragment, EventFragment, Fragment, FunctionFragment, ParamType, FormatTypes, AbiCoder, defaultAbiCoder, Interface, Indexed, CoerceFunc, JsonFragment, JsonFragmentType, Result, checkResultErrors, LogDescription, TransactionDescription }; | ||
export { ConstructorFragment, ErrorFragment, EventFragment, Fragment, FunctionFragment, ParamType, FormatTypes, AbiCoder, defaultAbiCoder, Interface, Indexed, CoerceFunc, JsonFragment, JsonFragmentType, Result, checkResultErrors, LogDescription, TransactionDescription }; | ||
//# sourceMappingURL=index.d.ts.map |
"use strict"; | ||
import { ConstructorFragment, EventFragment, FormatTypes, Fragment, FunctionFragment, ParamType } from "./fragments"; | ||
import { ConstructorFragment, ErrorFragment, EventFragment, FormatTypes, Fragment, FunctionFragment, ParamType } from "./fragments"; | ||
import { AbiCoder, defaultAbiCoder } from "./abi-coder"; | ||
import { checkResultErrors, Indexed, Interface, LogDescription, TransactionDescription } from "./interface"; | ||
export { ConstructorFragment, EventFragment, Fragment, FunctionFragment, ParamType, FormatTypes, AbiCoder, defaultAbiCoder, Interface, Indexed, checkResultErrors, LogDescription, TransactionDescription }; | ||
export { ConstructorFragment, ErrorFragment, EventFragment, Fragment, FunctionFragment, ParamType, FormatTypes, AbiCoder, defaultAbiCoder, Interface, Indexed, checkResultErrors, LogDescription, TransactionDescription }; | ||
//# sourceMappingURL=index.js.map |
@@ -6,3 +6,3 @@ import { BigNumber, BigNumberish } from "@ethersproject/bignumber"; | ||
import { checkResultErrors, Result } from "./coders/abstract-coder"; | ||
import { ConstructorFragment, EventFragment, Fragment, FunctionFragment, JsonFragment, ParamType } from "./fragments"; | ||
import { ConstructorFragment, ErrorFragment, EventFragment, Fragment, FunctionFragment, JsonFragment, ParamType } from "./fragments"; | ||
export { checkResultErrors, Result }; | ||
@@ -24,2 +24,9 @@ export declare class LogDescription extends Description<LogDescription> { | ||
} | ||
export declare class ErrorDescription extends Description<ErrorDescription> { | ||
readonly errorFragment: ErrorFragment; | ||
readonly name: string; | ||
readonly args: Result; | ||
readonly signature: string; | ||
readonly sighash: string; | ||
} | ||
export declare class Indexed extends Description<Indexed> { | ||
@@ -31,5 +38,5 @@ readonly hash: string; | ||
export declare class Interface { | ||
readonly fragments: Array<Fragment>; | ||
readonly fragments: ReadonlyArray<Fragment>; | ||
readonly errors: { | ||
[name: string]: any; | ||
[name: string]: ErrorFragment; | ||
}; | ||
@@ -48,25 +55,28 @@ readonly events: { | ||
readonly _isInterface: boolean; | ||
constructor(fragments: string | Array<Fragment | JsonFragment | string>); | ||
constructor(fragments: string | ReadonlyArray<Fragment | JsonFragment | string>); | ||
format(format?: string): string | Array<string>; | ||
static getAbiCoder(): AbiCoder; | ||
static getAddress(address: string): string; | ||
static getSighash(functionFragment: FunctionFragment): string; | ||
static getSighash(fragment: ErrorFragment | FunctionFragment): string; | ||
static getEventTopic(eventFragment: EventFragment): string; | ||
getFunction(nameOrSignatureOrSighash: string): FunctionFragment; | ||
getEvent(nameOrSignatureOrTopic: string): EventFragment; | ||
getSighash(functionFragment: FunctionFragment | string): string; | ||
getError(nameOrSignatureOrSighash: string): ErrorFragment; | ||
getSighash(fragment: ErrorFragment | FunctionFragment | string): string; | ||
getEventTopic(eventFragment: EventFragment | string): string; | ||
_decodeParams(params: Array<ParamType>, data: BytesLike): Result; | ||
_encodeParams(params: Array<ParamType>, values: Array<any>): string; | ||
encodeDeploy(values?: Array<any>): string; | ||
_decodeParams(params: ReadonlyArray<ParamType>, data: BytesLike): Result; | ||
_encodeParams(params: ReadonlyArray<ParamType>, values: ReadonlyArray<any>): string; | ||
encodeDeploy(values?: ReadonlyArray<any>): string; | ||
decodeErrorResult(fragment: ErrorFragment | string, data: BytesLike): Result; | ||
encodeErrorResult(fragment: ErrorFragment | string, values?: ReadonlyArray<any>): string; | ||
decodeFunctionData(functionFragment: FunctionFragment | string, data: BytesLike): Result; | ||
encodeFunctionData(functionFragment: FunctionFragment | string, values?: Array<any>): string; | ||
encodeFunctionData(functionFragment: FunctionFragment | string, values?: ReadonlyArray<any>): string; | ||
decodeFunctionResult(functionFragment: FunctionFragment | string, data: BytesLike): Result; | ||
encodeFunctionResult(functionFragment: FunctionFragment | string, values?: Array<any>): string; | ||
encodeFilterTopics(eventFragment: EventFragment, values: Array<any>): Array<string | Array<string>>; | ||
encodeEventLog(eventFragment: EventFragment, values: Array<any>): { | ||
encodeFunctionResult(functionFragment: FunctionFragment | string, values?: ReadonlyArray<any>): string; | ||
encodeFilterTopics(eventFragment: EventFragment | string, values: ReadonlyArray<any>): Array<string | Array<string>>; | ||
encodeEventLog(eventFragment: EventFragment | string, values: ReadonlyArray<any>): { | ||
data: string; | ||
topics: Array<string>; | ||
}; | ||
decodeEventLog(eventFragment: EventFragment | string, data: BytesLike, topics?: Array<string>): Result; | ||
decodeEventLog(eventFragment: EventFragment | string, data: BytesLike, topics?: ReadonlyArray<string>): Result; | ||
parseTransaction(tx: { | ||
@@ -80,4 +90,5 @@ data: string; | ||
}): LogDescription; | ||
parseError(data: BytesLike): ErrorDescription; | ||
static isInterface(value: any): value is Interface; | ||
} | ||
//# sourceMappingURL=interface.d.ts.map |
@@ -19,2 +19,4 @@ "use strict"; | ||
} | ||
export class ErrorDescription extends Description { | ||
} | ||
export class Indexed extends Description { | ||
@@ -25,2 +27,6 @@ static isIndexed(value) { | ||
} | ||
const BuiltinErrors = { | ||
"0x08c379a0": { signature: "Error(string)", name: "Error", inputs: ["string"], reason: true }, | ||
"0x4e487b71": { signature: "Panic(uint256)", name: "Panic", inputs: ["uint256"] } | ||
}; | ||
function wrapAccessError(property, error) { | ||
@@ -46,3 +52,2 @@ const wrap = new Error(`deferred error during ABI decoding triggered accessing ${property}`); | ||
constructor(fragments) { | ||
logger.checkNew(new.target, Interface); | ||
let abi = []; | ||
@@ -58,3 +63,3 @@ if (typeof (fragments) === "string") { | ||
}).filter((fragment) => (fragment != null))); | ||
defineReadOnly(this, "_abiCoder", getStatic((new.target), "getAbiCoder")()); | ||
defineReadOnly(this, "_abiCoder", getStatic(new.target, "getAbiCoder")()); | ||
defineReadOnly(this, "functions", {}); | ||
@@ -85,2 +90,5 @@ defineReadOnly(this, "errors", {}); | ||
break; | ||
case "error": | ||
bucket = this.errors; | ||
break; | ||
default: | ||
@@ -126,4 +134,4 @@ return; | ||
} | ||
static getSighash(functionFragment) { | ||
return hexDataSlice(id(functionFragment.format()), 0, 4); | ||
static getSighash(fragment) { | ||
return hexDataSlice(id(fragment.format()), 0, 4); | ||
} | ||
@@ -155,3 +163,3 @@ static getEventTopic(eventFragment) { | ||
} | ||
// Normlize the signature and lookup the function | ||
// Normalize the signature and lookup the function | ||
const result = this.functions[FunctionFragment.fromString(nameOrSignatureOrSighash).format()]; | ||
@@ -186,3 +194,3 @@ if (!result) { | ||
} | ||
// Normlize the signature and lookup the function | ||
// Normalize the signature and lookup the function | ||
const result = this.events[EventFragment.fromString(nameOrSignatureOrTopic).format()]; | ||
@@ -194,8 +202,49 @@ if (!result) { | ||
} | ||
// Find a function definition by any means necessary (unless it is ambiguous) | ||
getError(nameOrSignatureOrSighash) { | ||
if (isHexString(nameOrSignatureOrSighash)) { | ||
const getSighash = getStatic(this.constructor, "getSighash"); | ||
for (const name in this.errors) { | ||
const error = this.errors[name]; | ||
if (nameOrSignatureOrSighash === getSighash(error)) { | ||
return this.errors[name]; | ||
} | ||
} | ||
logger.throwArgumentError("no matching error", "sighash", nameOrSignatureOrSighash); | ||
} | ||
// It is a bare name, look up the function (will return null if ambiguous) | ||
if (nameOrSignatureOrSighash.indexOf("(") === -1) { | ||
const name = nameOrSignatureOrSighash.trim(); | ||
const matching = Object.keys(this.errors).filter((f) => (f.split("(" /* fix:) */)[0] === name)); | ||
if (matching.length === 0) { | ||
logger.throwArgumentError("no matching error", "name", name); | ||
} | ||
else if (matching.length > 1) { | ||
logger.throwArgumentError("multiple matching errors", "name", name); | ||
} | ||
return this.errors[matching[0]]; | ||
} | ||
// Normalize the signature and lookup the function | ||
const result = this.errors[FunctionFragment.fromString(nameOrSignatureOrSighash).format()]; | ||
if (!result) { | ||
logger.throwArgumentError("no matching error", "signature", nameOrSignatureOrSighash); | ||
} | ||
return result; | ||
} | ||
// Get the sighash (the bytes4 selector) used by Solidity to identify a function | ||
getSighash(functionFragment) { | ||
if (typeof (functionFragment) === "string") { | ||
functionFragment = this.getFunction(functionFragment); | ||
getSighash(fragment) { | ||
if (typeof (fragment) === "string") { | ||
try { | ||
fragment = this.getFunction(fragment); | ||
} | ||
catch (error) { | ||
try { | ||
fragment = this.getError(fragment); | ||
} | ||
catch (_) { | ||
throw error; | ||
} | ||
} | ||
} | ||
return getStatic(this.constructor, "getSighash")(functionFragment); | ||
return getStatic(this.constructor, "getSighash")(fragment); | ||
} | ||
@@ -218,2 +267,21 @@ // Get the topic (the bytes32 hash) used by Solidity to identify an event | ||
} | ||
decodeErrorResult(fragment, data) { | ||
if (typeof (fragment) === "string") { | ||
fragment = this.getError(fragment); | ||
} | ||
const bytes = arrayify(data); | ||
if (hexlify(bytes.slice(0, 4)) !== this.getSighash(fragment)) { | ||
logger.throwArgumentError(`data signature does not match error ${fragment.name}.`, "data", hexlify(bytes)); | ||
} | ||
return this._decodeParams(fragment.inputs, bytes.slice(4)); | ||
} | ||
encodeErrorResult(fragment, values) { | ||
if (typeof (fragment) === "string") { | ||
fragment = this.getError(fragment); | ||
} | ||
return hexlify(concat([ | ||
this.getSighash(fragment), | ||
this._encodeParams(fragment.inputs, values || []) | ||
])); | ||
} | ||
// Decode the data for a function call (e.g. tx.data) | ||
@@ -247,2 +315,5 @@ decodeFunctionData(functionFragment, data) { | ||
let reason = null; | ||
let message = ""; | ||
let errorArgs = null; | ||
let errorName = null; | ||
let errorSignature = null; | ||
@@ -256,14 +327,34 @@ switch (bytes.length % this._abiCoder._getWordSize()) { | ||
break; | ||
case 4: | ||
if (hexlify(bytes.slice(0, 4)) === "0x08c379a0") { | ||
errorSignature = "Error(string)"; | ||
reason = this._abiCoder.decode(["string"], bytes.slice(4))[0]; | ||
case 4: { | ||
const selector = hexlify(bytes.slice(0, 4)); | ||
const builtin = BuiltinErrors[selector]; | ||
if (builtin) { | ||
errorArgs = this._abiCoder.decode(builtin.inputs, bytes.slice(4)); | ||
errorName = builtin.name; | ||
errorSignature = builtin.signature; | ||
if (builtin.reason) { | ||
reason = errorArgs[0]; | ||
} | ||
if (errorName === "Error") { | ||
message = `; VM Exception while processing transaction: reverted with reason string ${JSON.stringify(errorArgs[0])}`; | ||
} | ||
else if (errorName === "Panic") { | ||
message = `; VM Exception while processing transaction: reverted with panic code ${errorArgs[0]}`; | ||
} | ||
} | ||
else { | ||
try { | ||
const error = this.getError(selector); | ||
errorArgs = this._abiCoder.decode(error.inputs, bytes.slice(4)); | ||
errorName = error.name; | ||
errorSignature = error.format(); | ||
} | ||
catch (error) { } | ||
} | ||
break; | ||
} | ||
} | ||
return logger.throwError("call revert exception", Logger.errors.CALL_EXCEPTION, { | ||
return logger.throwError("call revert exception" + message, Logger.errors.CALL_EXCEPTION, { | ||
method: functionFragment.format(), | ||
errorSignature: errorSignature, | ||
errorArgs: [reason], | ||
reason: reason | ||
data: hexlify(data), errorArgs, errorName, errorSignature, reason | ||
}); | ||
@@ -300,2 +391,8 @@ } | ||
} | ||
if (param.type === "bool" && typeof (value) === "boolean") { | ||
value = (value ? "0x01" : "0x00"); | ||
} | ||
if (param.type.match(/^u?int/)) { | ||
value = BigNumber.from(value).toHexString(); | ||
} | ||
// Check addresses are valid | ||
@@ -357,3 +454,3 @@ if (param.type === "address") { | ||
else if (param.baseType === "tuple" || param.baseType === "array") { | ||
// @TOOD | ||
// @TODO | ||
throw new Error("not implemented"); | ||
@@ -441,2 +538,3 @@ } | ||
Object.defineProperty(result, param.name, { | ||
enumerable: true, | ||
get: () => { throw wrapAccessError(`property ${JSON.stringify(param.name)}`, value); } | ||
@@ -455,2 +553,3 @@ }); | ||
Object.defineProperty(result, i, { | ||
enumerable: true, | ||
get: () => { throw wrapAccessError(`index ${i}`, value); } | ||
@@ -478,2 +577,4 @@ }); | ||
} | ||
// @TODO | ||
//parseCallResult(data: BytesLike): ?? | ||
// Given an event log, find the matching event fragment (if any) and | ||
@@ -488,3 +589,3 @@ // determine all its properties and values | ||
// Probably not, because just because it is the only event in the ABI does | ||
// not mean we have the full ABI; maybe jsut a fragment? | ||
// not mean we have the full ABI; maybe just a fragment? | ||
return new LogDescription({ | ||
@@ -498,2 +599,16 @@ eventFragment: fragment, | ||
} | ||
parseError(data) { | ||
const hexData = hexlify(data); | ||
let fragment = this.getError(hexData.substring(0, 10).toLowerCase()); | ||
if (!fragment) { | ||
return null; | ||
} | ||
return new ErrorDescription({ | ||
args: this._abiCoder.decode(fragment.inputs, "0x" + hexData.substring(10)), | ||
errorFragment: fragment, | ||
name: fragment.name, | ||
signature: fragment.format(), | ||
sighash: this.getSighash(fragment), | ||
}); | ||
} | ||
/* | ||
@@ -500,0 +615,0 @@ static from(value: Array<Fragment | string | JsonAbi> | string | Interface) { |
@@ -1,2 +0,2 @@ | ||
export declare const version = "abi/5.0.12"; | ||
export declare const version = "abi/5.7.0"; | ||
//# sourceMappingURL=_version.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.version = "abi/5.0.12"; | ||
exports.version = void 0; | ||
exports.version = "abi/5.7.0"; | ||
//# sourceMappingURL=_version.js.map |
@@ -12,7 +12,7 @@ import { BytesLike } from "@ethersproject/bytes"; | ||
_getWriter(): Writer; | ||
getDefaultValue(types: Array<string | ParamType>): Result; | ||
encode(types: Array<string | ParamType>, values: Array<any>): string; | ||
decode(types: Array<string | ParamType>, data: BytesLike, loose?: boolean): Result; | ||
getDefaultValue(types: ReadonlyArray<string | ParamType>): Result; | ||
encode(types: ReadonlyArray<string | ParamType>, values: ReadonlyArray<any>): string; | ||
decode(types: ReadonlyArray<string | ParamType>, data: BytesLike, loose?: boolean): Result; | ||
} | ||
export declare const defaultAbiCoder: AbiCoder; | ||
//# sourceMappingURL=abi-coder.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.defaultAbiCoder = exports.AbiCoder = void 0; | ||
// See: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI | ||
@@ -24,5 +25,3 @@ var bytes_1 = require("@ethersproject/bytes"); | ||
function AbiCoder(coerceFunc) { | ||
var _newTarget = this.constructor; | ||
logger.checkNew(_newTarget, AbiCoder); | ||
properties_1.defineReadOnly(this, "coerceFunc", coerceFunc || null); | ||
(0, properties_1.defineReadOnly)(this, "coerceFunc", coerceFunc || null); | ||
} | ||
@@ -100,3 +99,3 @@ AbiCoder.prototype._getCoder = function (param) { | ||
var coder = new tuple_1.TupleCoder(coders, "_"); | ||
return coder.decode(this._getReader(bytes_1.arrayify(data), loose)); | ||
return coder.decode(this._getReader((0, bytes_1.arrayify)(data), loose)); | ||
}; | ||
@@ -103,0 +102,0 @@ return AbiCoder; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Reader = exports.Writer = exports.Coder = exports.checkResultErrors = void 0; | ||
var bytes_1 = require("@ethersproject/bytes"); | ||
@@ -47,3 +48,3 @@ var bignumber_1 = require("@ethersproject/bignumber"); | ||
function Writer(wordSize) { | ||
properties_1.defineReadOnly(this, "wordSize", wordSize || 32); | ||
(0, properties_1.defineReadOnly)(this, "wordSize", wordSize || 32); | ||
this._data = []; | ||
@@ -55,5 +56,5 @@ this._dataLength = 0; | ||
get: function () { | ||
return bytes_1.hexConcat(this._data); | ||
return (0, bytes_1.hexConcat)(this._data); | ||
}, | ||
enumerable: true, | ||
enumerable: false, | ||
configurable: true | ||
@@ -63,3 +64,3 @@ }); | ||
get: function () { return this._dataLength; }, | ||
enumerable: true, | ||
enumerable: false, | ||
configurable: true | ||
@@ -73,10 +74,10 @@ }); | ||
Writer.prototype.appendWriter = function (writer) { | ||
return this._writeData(bytes_1.concat(writer._data)); | ||
return this._writeData((0, bytes_1.concat)(writer._data)); | ||
}; | ||
// Arrayish items; padded on the right to wordSize | ||
Writer.prototype.writeBytes = function (value) { | ||
var bytes = bytes_1.arrayify(value); | ||
var bytes = (0, bytes_1.arrayify)(value); | ||
var paddingOffset = bytes.length % this.wordSize; | ||
if (paddingOffset) { | ||
bytes = bytes_1.concat([bytes, this._padding.slice(paddingOffset)]); | ||
bytes = (0, bytes_1.concat)([bytes, this._padding.slice(paddingOffset)]); | ||
} | ||
@@ -86,3 +87,3 @@ return this._writeData(bytes); | ||
Writer.prototype._getValue = function (value) { | ||
var bytes = bytes_1.arrayify(bignumber_1.BigNumber.from(value)); | ||
var bytes = (0, bytes_1.arrayify)(bignumber_1.BigNumber.from(value)); | ||
if (bytes.length > this.wordSize) { | ||
@@ -95,3 +96,3 @@ logger.throwError("value out-of-bounds", logger_1.Logger.errors.BUFFER_OVERRUN, { | ||
if (bytes.length % this.wordSize) { | ||
bytes = bytes_1.concat([this._padding.slice(bytes.length % this.wordSize), bytes]); | ||
bytes = (0, bytes_1.concat)([this._padding.slice(bytes.length % this.wordSize), bytes]); | ||
} | ||
@@ -118,11 +119,11 @@ return bytes; | ||
function Reader(data, wordSize, coerceFunc, allowLoose) { | ||
properties_1.defineReadOnly(this, "_data", bytes_1.arrayify(data)); | ||
properties_1.defineReadOnly(this, "wordSize", wordSize || 32); | ||
properties_1.defineReadOnly(this, "_coerceFunc", coerceFunc); | ||
properties_1.defineReadOnly(this, "allowLoose", allowLoose); | ||
(0, properties_1.defineReadOnly)(this, "_data", (0, bytes_1.arrayify)(data)); | ||
(0, properties_1.defineReadOnly)(this, "wordSize", wordSize || 32); | ||
(0, properties_1.defineReadOnly)(this, "_coerceFunc", coerceFunc); | ||
(0, properties_1.defineReadOnly)(this, "allowLoose", allowLoose); | ||
this._offset = 0; | ||
} | ||
Object.defineProperty(Reader.prototype, "data", { | ||
get: function () { return bytes_1.hexlify(this._data); }, | ||
enumerable: true, | ||
get: function () { return (0, bytes_1.hexlify)(this._data); }, | ||
enumerable: false, | ||
configurable: true | ||
@@ -132,3 +133,3 @@ }); | ||
get: function () { return this._offset; }, | ||
enumerable: true, | ||
enumerable: false, | ||
configurable: true | ||
@@ -135,0 +136,0 @@ }); |
@@ -6,6 +6,8 @@ "use strict"; | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -17,2 +19,3 @@ function __() { this.constructor = d; } | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.AddressCoder = void 0; | ||
var address_1 = require("@ethersproject/address"); | ||
@@ -31,3 +34,3 @@ var bytes_1 = require("@ethersproject/bytes"); | ||
try { | ||
address_1.getAddress(value); | ||
value = (0, address_1.getAddress)(value); | ||
} | ||
@@ -40,3 +43,3 @@ catch (error) { | ||
AddressCoder.prototype.decode = function (reader) { | ||
return address_1.getAddress(bytes_1.hexZeroPad(reader.readValue().toHexString(), 20)); | ||
return (0, address_1.getAddress)((0, bytes_1.hexZeroPad)(reader.readValue().toHexString(), 20)); | ||
}; | ||
@@ -43,0 +46,0 @@ return AddressCoder; |
@@ -6,6 +6,8 @@ "use strict"; | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -17,2 +19,3 @@ function __() { this.constructor = d; } | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.AnonymousCoder = void 0; | ||
var abstract_coder_1 = require("./abstract-coder"); | ||
@@ -19,0 +22,0 @@ // Clones the functionality of an existing Coder, but without a localName |
@@ -6,6 +6,8 @@ "use strict"; | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -17,2 +19,3 @@ function __() { this.constructor = d; } | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ArrayCoder = exports.unpack = exports.pack = void 0; | ||
var logger_1 = require("@ethersproject/logger"); | ||
@@ -151,2 +154,3 @@ var _version_1 = require("../_version"); | ||
Object.defineProperty(values, name, { | ||
enumerable: true, | ||
get: function () { throw value; } | ||
@@ -163,2 +167,3 @@ }); | ||
Object.defineProperty(values, i, { | ||
enumerable: true, | ||
get: function () { throw value; } | ||
@@ -214,2 +219,13 @@ }); | ||
count = reader.readValue().toNumber(); | ||
// Check that there is *roughly* enough data to ensure | ||
// stray random data is not being read as a length. Each | ||
// slot requires at least 32 bytes for their value (or 32 | ||
// bytes as a link to the data). This could use a much | ||
// tighter bound, but we are erroring on the side of safety. | ||
if (count * 32 > reader._data.length) { | ||
logger.throwError("insufficient data length", logger_1.Logger.errors.BUFFER_OVERRUN, { | ||
length: reader._data.length, | ||
count: count | ||
}); | ||
} | ||
} | ||
@@ -216,0 +232,0 @@ var coders = []; |
@@ -6,6 +6,8 @@ "use strict"; | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -17,2 +19,3 @@ function __() { this.constructor = d; } | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.BooleanCoder = void 0; | ||
var abstract_coder_1 = require("./abstract-coder"); | ||
@@ -19,0 +22,0 @@ var BooleanCoder = /** @class */ (function (_super) { |
@@ -6,6 +6,8 @@ "use strict"; | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -17,2 +19,3 @@ function __() { this.constructor = d; } | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.BytesCoder = exports.DynamicBytesCoder = void 0; | ||
var bytes_1 = require("@ethersproject/bytes"); | ||
@@ -29,3 +32,3 @@ var abstract_coder_1 = require("./abstract-coder"); | ||
DynamicBytesCoder.prototype.encode = function (writer, value) { | ||
value = bytes_1.arrayify(value); | ||
value = (0, bytes_1.arrayify)(value); | ||
var length = writer.writeValue(value.length); | ||
@@ -47,3 +50,3 @@ length += writer.writeBytes(value); | ||
BytesCoder.prototype.decode = function (reader) { | ||
return reader.coerce(this.name, bytes_1.hexlify(_super.prototype.decode.call(this, reader))); | ||
return reader.coerce(this.name, (0, bytes_1.hexlify)(_super.prototype.decode.call(this, reader))); | ||
}; | ||
@@ -50,0 +53,0 @@ return BytesCoder; |
@@ -6,6 +6,8 @@ "use strict"; | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -17,2 +19,3 @@ function __() { this.constructor = d; } | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.FixedBytesCoder = void 0; | ||
var bytes_1 = require("@ethersproject/bytes"); | ||
@@ -34,3 +37,3 @@ var abstract_coder_1 = require("./abstract-coder"); | ||
FixedBytesCoder.prototype.encode = function (writer, value) { | ||
var data = bytes_1.arrayify(value); | ||
var data = (0, bytes_1.arrayify)(value); | ||
if (data.length !== this.size) { | ||
@@ -42,3 +45,3 @@ this._throwError("incorrect data length", value); | ||
FixedBytesCoder.prototype.decode = function (reader) { | ||
return reader.coerce(this.name, bytes_1.hexlify(reader.readBytes(this.size))); | ||
return reader.coerce(this.name, (0, bytes_1.hexlify)(reader.readBytes(this.size))); | ||
}; | ||
@@ -45,0 +48,0 @@ return FixedBytesCoder; |
@@ -6,6 +6,8 @@ "use strict"; | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -17,2 +19,3 @@ function __() { this.constructor = d; } | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.NullCoder = void 0; | ||
var abstract_coder_1 = require("./abstract-coder"); | ||
@@ -19,0 +22,0 @@ var NullCoder = /** @class */ (function (_super) { |
@@ -6,6 +6,8 @@ "use strict"; | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -17,2 +19,3 @@ function __() { this.constructor = d; } | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.NumberCoder = void 0; | ||
var bignumber_1 = require("@ethersproject/bignumber"); | ||
@@ -19,0 +22,0 @@ var constants_1 = require("@ethersproject/constants"); |
@@ -6,6 +6,8 @@ "use strict"; | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -17,2 +19,3 @@ function __() { this.constructor = d; } | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.StringCoder = void 0; | ||
var strings_1 = require("@ethersproject/strings"); | ||
@@ -29,6 +32,6 @@ var bytes_1 = require("./bytes"); | ||
StringCoder.prototype.encode = function (writer, value) { | ||
return _super.prototype.encode.call(this, writer, strings_1.toUtf8Bytes(value)); | ||
return _super.prototype.encode.call(this, writer, (0, strings_1.toUtf8Bytes)(value)); | ||
}; | ||
StringCoder.prototype.decode = function (reader) { | ||
return strings_1.toUtf8String(_super.prototype.decode.call(this, reader)); | ||
return (0, strings_1.toUtf8String)(_super.prototype.decode.call(this, reader)); | ||
}; | ||
@@ -35,0 +38,0 @@ return StringCoder; |
@@ -6,6 +6,8 @@ "use strict"; | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -17,2 +19,3 @@ function __() { this.constructor = d; } | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.TupleCoder = void 0; | ||
var abstract_coder_1 = require("./abstract-coder"); | ||
@@ -70,6 +73,6 @@ var array_1 = require("./array"); | ||
TupleCoder.prototype.encode = function (writer, value) { | ||
return array_1.pack(writer, this.coders, value); | ||
return (0, array_1.pack)(writer, this.coders, value); | ||
}; | ||
TupleCoder.prototype.decode = function (reader) { | ||
return reader.coerce(this.name, array_1.unpack(reader, this.coders)); | ||
return reader.coerce(this.name, (0, array_1.unpack)(reader, this.coders)); | ||
}; | ||
@@ -76,0 +79,0 @@ return TupleCoder; |
import { BigNumber } from "@ethersproject/bignumber"; | ||
export interface JsonFragmentType { | ||
name?: string; | ||
indexed?: boolean; | ||
type?: string; | ||
components?: Array<JsonFragmentType>; | ||
readonly name?: string; | ||
readonly indexed?: boolean; | ||
readonly type?: string; | ||
readonly internalType?: any; | ||
readonly components?: ReadonlyArray<JsonFragmentType>; | ||
} | ||
export interface JsonFragment { | ||
name?: string; | ||
type?: string; | ||
anonymous?: boolean; | ||
payable?: boolean; | ||
constant?: boolean; | ||
stateMutability?: string; | ||
inputs?: Array<JsonFragmentType>; | ||
outputs?: Array<JsonFragmentType>; | ||
gas?: string; | ||
readonly name?: string; | ||
readonly type?: string; | ||
readonly anonymous?: boolean; | ||
readonly payable?: boolean; | ||
readonly constant?: boolean; | ||
readonly stateMutability?: string; | ||
readonly inputs?: ReadonlyArray<JsonFragmentType>; | ||
readonly outputs?: ReadonlyArray<JsonFragmentType>; | ||
readonly gas?: string; | ||
} | ||
@@ -77,2 +78,9 @@ export declare const FormatTypes: { | ||
} | ||
export declare class ErrorFragment extends Fragment { | ||
format(format?: string): string; | ||
static from(value: ErrorFragment | JsonFragment | string): ErrorFragment; | ||
static fromObject(value: ErrorFragment | JsonFragment): ErrorFragment; | ||
static fromString(value: string): ErrorFragment; | ||
static isErrorFragment(value: any): value is ErrorFragment; | ||
} | ||
//# sourceMappingURL=fragments.d.ts.map |
@@ -6,6 +6,8 @@ "use strict"; | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -17,2 +19,3 @@ function __() { this.constructor = d; } | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ErrorFragment = exports.FunctionFragment = exports.ConstructorFragment = exports.EventFragment = exports.Fragment = exports.ParamType = exports.FormatTypes = void 0; | ||
var bignumber_1 = require("@ethersproject/bignumber"); | ||
@@ -212,3 +215,3 @@ var properties_1 = require("@ethersproject/properties"); | ||
for (var key in params) { | ||
properties_1.defineReadOnly(object, key, params[key]); | ||
(0, properties_1.defineReadOnly)(object, key, params[key]); | ||
} | ||
@@ -221,3 +224,3 @@ } | ||
minimal: "minimal", | ||
// Human-Readble with nice spacing, including all names | ||
// Human-Readable with nice spacing, including all names | ||
full: "full", | ||
@@ -260,3 +263,3 @@ // JSON-format a la Solidity | ||
// - minimal: "tuple(uint256,address) indexed" | ||
// - full: "tuple(uint256 foo, addres bar) indexed baz" | ||
// - full: "tuple(uint256 foo, address bar) indexed baz" | ||
ParamType.prototype.format = function (format) { | ||
@@ -378,2 +381,4 @@ if (!format) { | ||
return ConstructorFragment.fromObject(value); | ||
case "error": | ||
return ErrorFragment.fromObject(value); | ||
case "fallback": | ||
@@ -400,2 +405,5 @@ case "receive": | ||
} | ||
else if (value.split(" ")[0] === "error") { | ||
return ErrorFragment.fromString(value.substring(5).trim()); | ||
} | ||
return logger.throwArgumentError("unsupported fragment", "value", value); | ||
@@ -776,6 +784,76 @@ }; | ||
exports.FunctionFragment = FunctionFragment; | ||
//export class ErrorFragment extends Fragment { | ||
//} | ||
//export class StructFragment extends Fragment { | ||
//} | ||
function checkForbidden(fragment) { | ||
var sig = fragment.format(); | ||
if (sig === "Error(string)" || sig === "Panic(uint256)") { | ||
logger.throwArgumentError("cannot specify user defined " + sig + " error", "fragment", fragment); | ||
} | ||
return fragment; | ||
} | ||
var ErrorFragment = /** @class */ (function (_super) { | ||
__extends(ErrorFragment, _super); | ||
function ErrorFragment() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
ErrorFragment.prototype.format = function (format) { | ||
if (!format) { | ||
format = exports.FormatTypes.sighash; | ||
} | ||
if (!exports.FormatTypes[format]) { | ||
logger.throwArgumentError("invalid format type", "format", format); | ||
} | ||
if (format === exports.FormatTypes.json) { | ||
return JSON.stringify({ | ||
type: "error", | ||
name: this.name, | ||
inputs: this.inputs.map(function (input) { return JSON.parse(input.format(format)); }), | ||
}); | ||
} | ||
var result = ""; | ||
if (format !== exports.FormatTypes.sighash) { | ||
result += "error "; | ||
} | ||
result += this.name + "(" + this.inputs.map(function (input) { return input.format(format); }).join((format === exports.FormatTypes.full) ? ", " : ",") + ") "; | ||
return result.trim(); | ||
}; | ||
ErrorFragment.from = function (value) { | ||
if (typeof (value) === "string") { | ||
return ErrorFragment.fromString(value); | ||
} | ||
return ErrorFragment.fromObject(value); | ||
}; | ||
ErrorFragment.fromObject = function (value) { | ||
if (ErrorFragment.isErrorFragment(value)) { | ||
return value; | ||
} | ||
if (value.type !== "error") { | ||
logger.throwArgumentError("invalid error object", "value", value); | ||
} | ||
var params = { | ||
type: value.type, | ||
name: verifyIdentifier(value.name), | ||
inputs: (value.inputs ? value.inputs.map(ParamType.fromObject) : []) | ||
}; | ||
return checkForbidden(new ErrorFragment(_constructorGuard, params)); | ||
}; | ||
ErrorFragment.fromString = function (value) { | ||
var params = { type: "error" }; | ||
var parens = value.match(regexParen); | ||
if (!parens) { | ||
logger.throwArgumentError("invalid error signature", "value", value); | ||
} | ||
params.name = parens[1].trim(); | ||
if (params.name) { | ||
verifyIdentifier(params.name); | ||
} | ||
params.inputs = parseParams(parens[2], false); | ||
return checkForbidden(ErrorFragment.fromObject(params)); | ||
}; | ||
ErrorFragment.isErrorFragment = function (value) { | ||
return (value && value._isFragment && value.type === "error"); | ||
}; | ||
return ErrorFragment; | ||
}(Fragment)); | ||
exports.ErrorFragment = ErrorFragment; | ||
function verifyType(type) { | ||
@@ -792,3 +870,4 @@ // These need to be transformed to their full description | ||
} | ||
var regexIdentifier = new RegExp("^[A-Za-z_][A-Za-z0-9_]*$"); | ||
// See: https://github.com/ethereum/solidity/blob/1f8f1a3db93a548d0555e3e14cfc55a10e25b60e/docs/grammar/SolidityLexer.g4#L234 | ||
var regexIdentifier = new RegExp("^[a-zA-Z$_][a-zA-Z0-9$_]*$"); | ||
function verifyIdentifier(value) { | ||
@@ -795,0 +874,0 @@ if (!value || !value.match(regexIdentifier)) { |
@@ -1,5 +0,5 @@ | ||
import { ConstructorFragment, EventFragment, FormatTypes, Fragment, FunctionFragment, JsonFragment, JsonFragmentType, ParamType } from "./fragments"; | ||
import { ConstructorFragment, ErrorFragment, EventFragment, FormatTypes, Fragment, FunctionFragment, JsonFragment, JsonFragmentType, ParamType } from "./fragments"; | ||
import { AbiCoder, CoerceFunc, defaultAbiCoder } from "./abi-coder"; | ||
import { checkResultErrors, Indexed, Interface, LogDescription, Result, TransactionDescription } from "./interface"; | ||
export { ConstructorFragment, EventFragment, Fragment, FunctionFragment, ParamType, FormatTypes, AbiCoder, defaultAbiCoder, Interface, Indexed, CoerceFunc, JsonFragment, JsonFragmentType, Result, checkResultErrors, LogDescription, TransactionDescription }; | ||
export { ConstructorFragment, ErrorFragment, EventFragment, Fragment, FunctionFragment, ParamType, FormatTypes, AbiCoder, defaultAbiCoder, Interface, Indexed, CoerceFunc, JsonFragment, JsonFragmentType, Result, checkResultErrors, LogDescription, TransactionDescription }; | ||
//# sourceMappingURL=index.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.TransactionDescription = exports.LogDescription = exports.checkResultErrors = exports.Indexed = exports.Interface = exports.defaultAbiCoder = exports.AbiCoder = exports.FormatTypes = exports.ParamType = exports.FunctionFragment = exports.Fragment = exports.EventFragment = exports.ErrorFragment = exports.ConstructorFragment = void 0; | ||
var fragments_1 = require("./fragments"); | ||
exports.ConstructorFragment = fragments_1.ConstructorFragment; | ||
exports.EventFragment = fragments_1.EventFragment; | ||
exports.FormatTypes = fragments_1.FormatTypes; | ||
exports.Fragment = fragments_1.Fragment; | ||
exports.FunctionFragment = fragments_1.FunctionFragment; | ||
exports.ParamType = fragments_1.ParamType; | ||
Object.defineProperty(exports, "ConstructorFragment", { enumerable: true, get: function () { return fragments_1.ConstructorFragment; } }); | ||
Object.defineProperty(exports, "ErrorFragment", { enumerable: true, get: function () { return fragments_1.ErrorFragment; } }); | ||
Object.defineProperty(exports, "EventFragment", { enumerable: true, get: function () { return fragments_1.EventFragment; } }); | ||
Object.defineProperty(exports, "FormatTypes", { enumerable: true, get: function () { return fragments_1.FormatTypes; } }); | ||
Object.defineProperty(exports, "Fragment", { enumerable: true, get: function () { return fragments_1.Fragment; } }); | ||
Object.defineProperty(exports, "FunctionFragment", { enumerable: true, get: function () { return fragments_1.FunctionFragment; } }); | ||
Object.defineProperty(exports, "ParamType", { enumerable: true, get: function () { return fragments_1.ParamType; } }); | ||
var abi_coder_1 = require("./abi-coder"); | ||
exports.AbiCoder = abi_coder_1.AbiCoder; | ||
exports.defaultAbiCoder = abi_coder_1.defaultAbiCoder; | ||
Object.defineProperty(exports, "AbiCoder", { enumerable: true, get: function () { return abi_coder_1.AbiCoder; } }); | ||
Object.defineProperty(exports, "defaultAbiCoder", { enumerable: true, get: function () { return abi_coder_1.defaultAbiCoder; } }); | ||
var interface_1 = require("./interface"); | ||
exports.checkResultErrors = interface_1.checkResultErrors; | ||
exports.Indexed = interface_1.Indexed; | ||
exports.Interface = interface_1.Interface; | ||
exports.LogDescription = interface_1.LogDescription; | ||
exports.TransactionDescription = interface_1.TransactionDescription; | ||
Object.defineProperty(exports, "checkResultErrors", { enumerable: true, get: function () { return interface_1.checkResultErrors; } }); | ||
Object.defineProperty(exports, "Indexed", { enumerable: true, get: function () { return interface_1.Indexed; } }); | ||
Object.defineProperty(exports, "Interface", { enumerable: true, get: function () { return interface_1.Interface; } }); | ||
Object.defineProperty(exports, "LogDescription", { enumerable: true, get: function () { return interface_1.LogDescription; } }); | ||
Object.defineProperty(exports, "TransactionDescription", { enumerable: true, get: function () { return interface_1.TransactionDescription; } }); | ||
//# sourceMappingURL=index.js.map |
@@ -6,3 +6,3 @@ import { BigNumber, BigNumberish } from "@ethersproject/bignumber"; | ||
import { checkResultErrors, Result } from "./coders/abstract-coder"; | ||
import { ConstructorFragment, EventFragment, Fragment, FunctionFragment, JsonFragment, ParamType } from "./fragments"; | ||
import { ConstructorFragment, ErrorFragment, EventFragment, Fragment, FunctionFragment, JsonFragment, ParamType } from "./fragments"; | ||
export { checkResultErrors, Result }; | ||
@@ -24,2 +24,9 @@ export declare class LogDescription extends Description<LogDescription> { | ||
} | ||
export declare class ErrorDescription extends Description<ErrorDescription> { | ||
readonly errorFragment: ErrorFragment; | ||
readonly name: string; | ||
readonly args: Result; | ||
readonly signature: string; | ||
readonly sighash: string; | ||
} | ||
export declare class Indexed extends Description<Indexed> { | ||
@@ -31,5 +38,5 @@ readonly hash: string; | ||
export declare class Interface { | ||
readonly fragments: Array<Fragment>; | ||
readonly fragments: ReadonlyArray<Fragment>; | ||
readonly errors: { | ||
[name: string]: any; | ||
[name: string]: ErrorFragment; | ||
}; | ||
@@ -48,25 +55,28 @@ readonly events: { | ||
readonly _isInterface: boolean; | ||
constructor(fragments: string | Array<Fragment | JsonFragment | string>); | ||
constructor(fragments: string | ReadonlyArray<Fragment | JsonFragment | string>); | ||
format(format?: string): string | Array<string>; | ||
static getAbiCoder(): AbiCoder; | ||
static getAddress(address: string): string; | ||
static getSighash(functionFragment: FunctionFragment): string; | ||
static getSighash(fragment: ErrorFragment | FunctionFragment): string; | ||
static getEventTopic(eventFragment: EventFragment): string; | ||
getFunction(nameOrSignatureOrSighash: string): FunctionFragment; | ||
getEvent(nameOrSignatureOrTopic: string): EventFragment; | ||
getSighash(functionFragment: FunctionFragment | string): string; | ||
getError(nameOrSignatureOrSighash: string): ErrorFragment; | ||
getSighash(fragment: ErrorFragment | FunctionFragment | string): string; | ||
getEventTopic(eventFragment: EventFragment | string): string; | ||
_decodeParams(params: Array<ParamType>, data: BytesLike): Result; | ||
_encodeParams(params: Array<ParamType>, values: Array<any>): string; | ||
encodeDeploy(values?: Array<any>): string; | ||
_decodeParams(params: ReadonlyArray<ParamType>, data: BytesLike): Result; | ||
_encodeParams(params: ReadonlyArray<ParamType>, values: ReadonlyArray<any>): string; | ||
encodeDeploy(values?: ReadonlyArray<any>): string; | ||
decodeErrorResult(fragment: ErrorFragment | string, data: BytesLike): Result; | ||
encodeErrorResult(fragment: ErrorFragment | string, values?: ReadonlyArray<any>): string; | ||
decodeFunctionData(functionFragment: FunctionFragment | string, data: BytesLike): Result; | ||
encodeFunctionData(functionFragment: FunctionFragment | string, values?: Array<any>): string; | ||
encodeFunctionData(functionFragment: FunctionFragment | string, values?: ReadonlyArray<any>): string; | ||
decodeFunctionResult(functionFragment: FunctionFragment | string, data: BytesLike): Result; | ||
encodeFunctionResult(functionFragment: FunctionFragment | string, values?: Array<any>): string; | ||
encodeFilterTopics(eventFragment: EventFragment, values: Array<any>): Array<string | Array<string>>; | ||
encodeEventLog(eventFragment: EventFragment, values: Array<any>): { | ||
encodeFunctionResult(functionFragment: FunctionFragment | string, values?: ReadonlyArray<any>): string; | ||
encodeFilterTopics(eventFragment: EventFragment | string, values: ReadonlyArray<any>): Array<string | Array<string>>; | ||
encodeEventLog(eventFragment: EventFragment | string, values: ReadonlyArray<any>): { | ||
data: string; | ||
topics: Array<string>; | ||
}; | ||
decodeEventLog(eventFragment: EventFragment | string, data: BytesLike, topics?: Array<string>): Result; | ||
decodeEventLog(eventFragment: EventFragment | string, data: BytesLike, topics?: ReadonlyArray<string>): Result; | ||
parseTransaction(tx: { | ||
@@ -80,4 +90,5 @@ data: string; | ||
}): LogDescription; | ||
parseError(data: BytesLike): ErrorDescription; | ||
static isInterface(value: any): value is Interface; | ||
} | ||
//# sourceMappingURL=interface.d.ts.map |
@@ -6,6 +6,8 @@ "use strict"; | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -17,2 +19,3 @@ function __() { this.constructor = d; } | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Interface = exports.Indexed = exports.ErrorDescription = exports.TransactionDescription = exports.LogDescription = exports.checkResultErrors = void 0; | ||
var address_1 = require("@ethersproject/address"); | ||
@@ -26,3 +29,3 @@ var bignumber_1 = require("@ethersproject/bignumber"); | ||
var abstract_coder_1 = require("./coders/abstract-coder"); | ||
exports.checkResultErrors = abstract_coder_1.checkResultErrors; | ||
Object.defineProperty(exports, "checkResultErrors", { enumerable: true, get: function () { return abstract_coder_1.checkResultErrors; } }); | ||
var fragments_1 = require("./fragments"); | ||
@@ -48,2 +51,10 @@ var logger_1 = require("@ethersproject/logger"); | ||
exports.TransactionDescription = TransactionDescription; | ||
var ErrorDescription = /** @class */ (function (_super) { | ||
__extends(ErrorDescription, _super); | ||
function ErrorDescription() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
return ErrorDescription; | ||
}(properties_1.Description)); | ||
exports.ErrorDescription = ErrorDescription; | ||
var Indexed = /** @class */ (function (_super) { | ||
@@ -60,2 +71,6 @@ __extends(Indexed, _super); | ||
exports.Indexed = Indexed; | ||
var BuiltinErrors = { | ||
"0x08c379a0": { signature: "Error(string)", name: "Error", inputs: ["string"], reason: true }, | ||
"0x4e487b71": { signature: "Panic(uint256)", name: "Panic", inputs: ["uint256"] } | ||
}; | ||
function wrapAccessError(property, error) { | ||
@@ -83,3 +98,2 @@ var wrap = new Error("deferred error during ABI decoding triggered accessing " + property); | ||
var _this = this; | ||
logger.checkNew(_newTarget, Interface); | ||
var abi = []; | ||
@@ -92,10 +106,10 @@ if (typeof (fragments) === "string") { | ||
} | ||
properties_1.defineReadOnly(this, "fragments", abi.map(function (fragment) { | ||
(0, properties_1.defineReadOnly)(this, "fragments", abi.map(function (fragment) { | ||
return fragments_1.Fragment.from(fragment); | ||
}).filter(function (fragment) { return (fragment != null); })); | ||
properties_1.defineReadOnly(this, "_abiCoder", properties_1.getStatic((_newTarget), "getAbiCoder")()); | ||
properties_1.defineReadOnly(this, "functions", {}); | ||
properties_1.defineReadOnly(this, "errors", {}); | ||
properties_1.defineReadOnly(this, "events", {}); | ||
properties_1.defineReadOnly(this, "structs", {}); | ||
(0, properties_1.defineReadOnly)(this, "_abiCoder", (0, properties_1.getStatic)(_newTarget, "getAbiCoder")()); | ||
(0, properties_1.defineReadOnly)(this, "functions", {}); | ||
(0, properties_1.defineReadOnly)(this, "errors", {}); | ||
(0, properties_1.defineReadOnly)(this, "events", {}); | ||
(0, properties_1.defineReadOnly)(this, "structs", {}); | ||
// Add all fragments by their signature | ||
@@ -111,3 +125,3 @@ this.fragments.forEach(function (fragment) { | ||
//checkNames(fragment, "input", fragment.inputs); | ||
properties_1.defineReadOnly(_this, "deploy", fragment); | ||
(0, properties_1.defineReadOnly)(_this, "deploy", fragment); | ||
return; | ||
@@ -123,2 +137,5 @@ case "function": | ||
break; | ||
case "error": | ||
bucket = _this.errors; | ||
break; | ||
default: | ||
@@ -136,3 +153,3 @@ return; | ||
if (!this.deploy) { | ||
properties_1.defineReadOnly(this, "deploy", fragments_1.ConstructorFragment.from({ | ||
(0, properties_1.defineReadOnly)(this, "deploy", fragments_1.ConstructorFragment.from({ | ||
payable: false, | ||
@@ -142,3 +159,3 @@ type: "constructor" | ||
} | ||
properties_1.defineReadOnly(this, "_isInterface", true); | ||
(0, properties_1.defineReadOnly)(this, "_isInterface", true); | ||
} | ||
@@ -164,13 +181,13 @@ Interface.prototype.format = function (format) { | ||
Interface.getAddress = function (address) { | ||
return address_1.getAddress(address); | ||
return (0, address_1.getAddress)(address); | ||
}; | ||
Interface.getSighash = function (functionFragment) { | ||
return bytes_1.hexDataSlice(hash_1.id(functionFragment.format()), 0, 4); | ||
Interface.getSighash = function (fragment) { | ||
return (0, bytes_1.hexDataSlice)((0, hash_1.id)(fragment.format()), 0, 4); | ||
}; | ||
Interface.getEventTopic = function (eventFragment) { | ||
return hash_1.id(eventFragment.format()); | ||
return (0, hash_1.id)(eventFragment.format()); | ||
}; | ||
// Find a function definition by any means necessary (unless it is ambiguous) | ||
Interface.prototype.getFunction = function (nameOrSignatureOrSighash) { | ||
if (bytes_1.isHexString(nameOrSignatureOrSighash)) { | ||
if ((0, bytes_1.isHexString)(nameOrSignatureOrSighash)) { | ||
for (var name_1 in this.functions) { | ||
@@ -195,3 +212,3 @@ if (nameOrSignatureOrSighash === this.getSighash(name_1)) { | ||
} | ||
// Normlize the signature and lookup the function | ||
// Normalize the signature and lookup the function | ||
var result = this.functions[fragments_1.FunctionFragment.fromString(nameOrSignatureOrSighash).format()]; | ||
@@ -205,3 +222,3 @@ if (!result) { | ||
Interface.prototype.getEvent = function (nameOrSignatureOrTopic) { | ||
if (bytes_1.isHexString(nameOrSignatureOrTopic)) { | ||
if ((0, bytes_1.isHexString)(nameOrSignatureOrTopic)) { | ||
var topichash = nameOrSignatureOrTopic.toLowerCase(); | ||
@@ -227,3 +244,3 @@ for (var name_3 in this.events) { | ||
} | ||
// Normlize the signature and lookup the function | ||
// Normalize the signature and lookup the function | ||
var result = this.events[fragments_1.EventFragment.fromString(nameOrSignatureOrTopic).format()]; | ||
@@ -235,8 +252,49 @@ if (!result) { | ||
}; | ||
// Find a function definition by any means necessary (unless it is ambiguous) | ||
Interface.prototype.getError = function (nameOrSignatureOrSighash) { | ||
if ((0, bytes_1.isHexString)(nameOrSignatureOrSighash)) { | ||
var getSighash = (0, properties_1.getStatic)(this.constructor, "getSighash"); | ||
for (var name_5 in this.errors) { | ||
var error = this.errors[name_5]; | ||
if (nameOrSignatureOrSighash === getSighash(error)) { | ||
return this.errors[name_5]; | ||
} | ||
} | ||
logger.throwArgumentError("no matching error", "sighash", nameOrSignatureOrSighash); | ||
} | ||
// It is a bare name, look up the function (will return null if ambiguous) | ||
if (nameOrSignatureOrSighash.indexOf("(") === -1) { | ||
var name_6 = nameOrSignatureOrSighash.trim(); | ||
var matching = Object.keys(this.errors).filter(function (f) { return (f.split("(" /* fix:) */)[0] === name_6); }); | ||
if (matching.length === 0) { | ||
logger.throwArgumentError("no matching error", "name", name_6); | ||
} | ||
else if (matching.length > 1) { | ||
logger.throwArgumentError("multiple matching errors", "name", name_6); | ||
} | ||
return this.errors[matching[0]]; | ||
} | ||
// Normalize the signature and lookup the function | ||
var result = this.errors[fragments_1.FunctionFragment.fromString(nameOrSignatureOrSighash).format()]; | ||
if (!result) { | ||
logger.throwArgumentError("no matching error", "signature", nameOrSignatureOrSighash); | ||
} | ||
return result; | ||
}; | ||
// Get the sighash (the bytes4 selector) used by Solidity to identify a function | ||
Interface.prototype.getSighash = function (functionFragment) { | ||
if (typeof (functionFragment) === "string") { | ||
functionFragment = this.getFunction(functionFragment); | ||
Interface.prototype.getSighash = function (fragment) { | ||
if (typeof (fragment) === "string") { | ||
try { | ||
fragment = this.getFunction(fragment); | ||
} | ||
catch (error) { | ||
try { | ||
fragment = this.getError(fragment); | ||
} | ||
catch (_) { | ||
throw error; | ||
} | ||
} | ||
} | ||
return properties_1.getStatic(this.constructor, "getSighash")(functionFragment); | ||
return (0, properties_1.getStatic)(this.constructor, "getSighash")(fragment); | ||
}; | ||
@@ -248,3 +306,3 @@ // Get the topic (the bytes32 hash) used by Solidity to identify an event | ||
} | ||
return properties_1.getStatic(this.constructor, "getEventTopic")(eventFragment); | ||
return (0, properties_1.getStatic)(this.constructor, "getEventTopic")(eventFragment); | ||
}; | ||
@@ -260,2 +318,21 @@ Interface.prototype._decodeParams = function (params, data) { | ||
}; | ||
Interface.prototype.decodeErrorResult = function (fragment, data) { | ||
if (typeof (fragment) === "string") { | ||
fragment = this.getError(fragment); | ||
} | ||
var bytes = (0, bytes_1.arrayify)(data); | ||
if ((0, bytes_1.hexlify)(bytes.slice(0, 4)) !== this.getSighash(fragment)) { | ||
logger.throwArgumentError("data signature does not match error " + fragment.name + ".", "data", (0, bytes_1.hexlify)(bytes)); | ||
} | ||
return this._decodeParams(fragment.inputs, bytes.slice(4)); | ||
}; | ||
Interface.prototype.encodeErrorResult = function (fragment, values) { | ||
if (typeof (fragment) === "string") { | ||
fragment = this.getError(fragment); | ||
} | ||
return (0, bytes_1.hexlify)((0, bytes_1.concat)([ | ||
this.getSighash(fragment), | ||
this._encodeParams(fragment.inputs, values || []) | ||
])); | ||
}; | ||
// Decode the data for a function call (e.g. tx.data) | ||
@@ -266,5 +343,5 @@ Interface.prototype.decodeFunctionData = function (functionFragment, data) { | ||
} | ||
var bytes = bytes_1.arrayify(data); | ||
if (bytes_1.hexlify(bytes.slice(0, 4)) !== this.getSighash(functionFragment)) { | ||
logger.throwArgumentError("data signature does not match function " + functionFragment.name + ".", "data", bytes_1.hexlify(bytes)); | ||
var bytes = (0, bytes_1.arrayify)(data); | ||
if ((0, bytes_1.hexlify)(bytes.slice(0, 4)) !== this.getSighash(functionFragment)) { | ||
logger.throwArgumentError("data signature does not match function " + functionFragment.name + ".", "data", (0, bytes_1.hexlify)(bytes)); | ||
} | ||
@@ -278,3 +355,3 @@ return this._decodeParams(functionFragment.inputs, bytes.slice(4)); | ||
} | ||
return bytes_1.hexlify(bytes_1.concat([ | ||
return (0, bytes_1.hexlify)((0, bytes_1.concat)([ | ||
this.getSighash(functionFragment), | ||
@@ -289,4 +366,7 @@ this._encodeParams(functionFragment.inputs, values || []) | ||
} | ||
var bytes = bytes_1.arrayify(data); | ||
var bytes = (0, bytes_1.arrayify)(data); | ||
var reason = null; | ||
var message = ""; | ||
var errorArgs = null; | ||
var errorName = null; | ||
var errorSignature = null; | ||
@@ -300,13 +380,37 @@ switch (bytes.length % this._abiCoder._getWordSize()) { | ||
break; | ||
case 4: | ||
if (bytes_1.hexlify(bytes.slice(0, 4)) === "0x08c379a0") { | ||
errorSignature = "Error(string)"; | ||
reason = this._abiCoder.decode(["string"], bytes.slice(4))[0]; | ||
case 4: { | ||
var selector = (0, bytes_1.hexlify)(bytes.slice(0, 4)); | ||
var builtin = BuiltinErrors[selector]; | ||
if (builtin) { | ||
errorArgs = this._abiCoder.decode(builtin.inputs, bytes.slice(4)); | ||
errorName = builtin.name; | ||
errorSignature = builtin.signature; | ||
if (builtin.reason) { | ||
reason = errorArgs[0]; | ||
} | ||
if (errorName === "Error") { | ||
message = "; VM Exception while processing transaction: reverted with reason string " + JSON.stringify(errorArgs[0]); | ||
} | ||
else if (errorName === "Panic") { | ||
message = "; VM Exception while processing transaction: reverted with panic code " + errorArgs[0]; | ||
} | ||
} | ||
else { | ||
try { | ||
var error = this.getError(selector); | ||
errorArgs = this._abiCoder.decode(error.inputs, bytes.slice(4)); | ||
errorName = error.name; | ||
errorSignature = error.format(); | ||
} | ||
catch (error) { } | ||
} | ||
break; | ||
} | ||
} | ||
return logger.throwError("call revert exception", logger_1.Logger.errors.CALL_EXCEPTION, { | ||
return logger.throwError("call revert exception" + message, logger_1.Logger.errors.CALL_EXCEPTION, { | ||
method: functionFragment.format(), | ||
data: (0, bytes_1.hexlify)(data), | ||
errorArgs: errorArgs, | ||
errorName: errorName, | ||
errorSignature: errorSignature, | ||
errorArgs: [reason], | ||
reason: reason | ||
@@ -320,3 +424,3 @@ }); | ||
} | ||
return bytes_1.hexlify(this._abiCoder.encode(functionFragment.outputs, values || [])); | ||
return (0, bytes_1.hexlify)(this._abiCoder.encode(functionFragment.outputs, values || [])); | ||
}; | ||
@@ -341,7 +445,13 @@ // Create the filter for the event with search criteria (e.g. for eth_filterLog) | ||
if (param.type === "string") { | ||
return hash_1.id(value); | ||
return (0, hash_1.id)(value); | ||
} | ||
else if (param.type === "bytes") { | ||
return keccak256_1.keccak256(bytes_1.hexlify(value)); | ||
return (0, keccak256_1.keccak256)((0, bytes_1.hexlify)(value)); | ||
} | ||
if (param.type === "bool" && typeof (value) === "boolean") { | ||
value = (value ? "0x01" : "0x00"); | ||
} | ||
if (param.type.match(/^u?int/)) { | ||
value = bignumber_1.BigNumber.from(value).toHexString(); | ||
} | ||
// Check addresses are valid | ||
@@ -351,3 +461,3 @@ if (param.type === "address") { | ||
} | ||
return bytes_1.hexZeroPad(bytes_1.hexlify(value), 32); | ||
return (0, bytes_1.hexZeroPad)((0, bytes_1.hexlify)(value), 32); | ||
}; | ||
@@ -399,9 +509,9 @@ values.forEach(function (value, index) { | ||
if (param.type === "string") { | ||
topics.push(hash_1.id(value)); | ||
topics.push((0, hash_1.id)(value)); | ||
} | ||
else if (param.type === "bytes") { | ||
topics.push(keccak256_1.keccak256(value)); | ||
topics.push((0, keccak256_1.keccak256)(value)); | ||
} | ||
else if (param.baseType === "tuple" || param.baseType === "array") { | ||
// @TOOD | ||
// @TODO | ||
throw new Error("not implemented"); | ||
@@ -430,3 +540,3 @@ } | ||
var topicHash = this.getEventTopic(eventFragment); | ||
if (!bytes_1.isHexString(topics[0], 32) || topics[0].toLowerCase() !== topicHash) { | ||
if (!(0, bytes_1.isHexString)(topics[0], 32) || topics[0].toLowerCase() !== topicHash) { | ||
logger.throwError("fragment/topic mismatch", logger_1.Logger.errors.INVALID_ARGUMENT, { argument: "topics[0]", expected: topicHash, value: topics[0] }); | ||
@@ -455,3 +565,3 @@ } | ||
}); | ||
var resultIndexed = (topics != null) ? this._abiCoder.decode(indexed, bytes_1.concat(topics)) : null; | ||
var resultIndexed = (topics != null) ? this._abiCoder.decode(indexed, (0, bytes_1.concat)(topics)) : null; | ||
var resultNonIndexed = this._abiCoder.decode(nonIndexed, data, true); | ||
@@ -491,2 +601,3 @@ var result = []; | ||
Object.defineProperty(result, param.name, { | ||
enumerable: true, | ||
get: function () { throw wrapAccessError("property " + JSON.stringify(param.name), value_1); } | ||
@@ -504,2 +615,3 @@ }); | ||
Object.defineProperty(result, i, { | ||
enumerable: true, | ||
get: function () { throw wrapAccessError("index " + i, value); } | ||
@@ -531,2 +643,4 @@ }); | ||
}; | ||
// @TODO | ||
//parseCallResult(data: BytesLike): ?? | ||
// Given an event log, find the matching event fragment (if any) and | ||
@@ -541,3 +655,3 @@ // determine all its properties and values | ||
// Probably not, because just because it is the only event in the ABI does | ||
// not mean we have the full ABI; maybe jsut a fragment? | ||
// not mean we have the full ABI; maybe just a fragment? | ||
return new LogDescription({ | ||
@@ -551,2 +665,16 @@ eventFragment: fragment, | ||
}; | ||
Interface.prototype.parseError = function (data) { | ||
var hexData = (0, bytes_1.hexlify)(data); | ||
var fragment = this.getError(hexData.substring(0, 10).toLowerCase()); | ||
if (!fragment) { | ||
return null; | ||
} | ||
return new ErrorDescription({ | ||
args: this._abiCoder.decode(fragment.inputs, "0x" + hexData.substring(10)), | ||
errorFragment: fragment, | ||
name: fragment.name, | ||
signature: fragment.format(), | ||
sighash: this.getSighash(fragment), | ||
}); | ||
}; | ||
/* | ||
@@ -553,0 +681,0 @@ static from(value: Array<Fragment | string | JsonAbi> | string | Interface) { |
{ | ||
"author": "Richard Moore <me@ricmoo.com>", | ||
"dependencies": { | ||
"@ethersproject/address": "^5.0.9", | ||
"@ethersproject/bignumber": "^5.0.13", | ||
"@ethersproject/bytes": "^5.0.9", | ||
"@ethersproject/constants": "^5.0.8", | ||
"@ethersproject/hash": "^5.0.10", | ||
"@ethersproject/keccak256": "^5.0.7", | ||
"@ethersproject/logger": "^5.0.8", | ||
"@ethersproject/properties": "^5.0.7", | ||
"@ethersproject/strings": "^5.0.8" | ||
"@ethersproject/address": "^5.7.0", | ||
"@ethersproject/bignumber": "^5.7.0", | ||
"@ethersproject/bytes": "^5.7.0", | ||
"@ethersproject/constants": "^5.7.0", | ||
"@ethersproject/hash": "^5.7.0", | ||
"@ethersproject/keccak256": "^5.7.0", | ||
"@ethersproject/logger": "^5.7.0", | ||
"@ethersproject/properties": "^5.7.0", | ||
"@ethersproject/strings": "^5.7.0" | ||
}, | ||
@@ -26,3 +26,3 @@ "description": "Utilities and Classes for parsing, formatting and managing Ethereum ABIs.", | ||
], | ||
"gitHead": "2333b6cfd28acef75905eed5e8ee46f8250c23e9", | ||
"gitHead": "ec1b9583039a14a0e0fa15d0a2a6082a2f41cf5b", | ||
"keywords": [ | ||
@@ -48,5 +48,5 @@ "Ethereum", | ||
"sideEffects": false, | ||
"tarballHash": "0x2792ba9c5d229dcebc7f5b03dea4cd0903da805115adb6211bb0aef5051d52d9", | ||
"tarballHash": "0x76f6fd1617e7f7aacd876957111e5368a7e53b8aebf572b30f0f1a0cd2b4a603", | ||
"types": "./lib/index.d.ts", | ||
"version": "5.0.12" | ||
"version": "5.7.0" | ||
} |
@@ -1,1 +0,1 @@ | ||
export const version = "abi/5.0.12"; | ||
export const version = "abi/5.7.0"; |
@@ -36,3 +36,2 @@ "use strict"; | ||
constructor(coerceFunc?: CoerceFunc) { | ||
logger.checkNew(new.target, AbiCoder); | ||
defineReadOnly(this, "coerceFunc", coerceFunc || null); | ||
@@ -95,3 +94,3 @@ } | ||
getDefaultValue(types: Array<string | ParamType>): Result { | ||
getDefaultValue(types: ReadonlyArray<string | ParamType>): Result { | ||
const coders: Array<Coder> = types.map((type) => this._getCoder(ParamType.from(type))); | ||
@@ -102,3 +101,3 @@ const coder = new TupleCoder(coders, "_"); | ||
encode(types: Array<string | ParamType>, values: Array<any>): string { | ||
encode(types: ReadonlyArray<string | ParamType>, values: ReadonlyArray<any>): string { | ||
if (types.length !== values.length) { | ||
@@ -119,3 +118,3 @@ logger.throwError("types/values length mismatch", Logger.errors.INVALID_ARGUMENT, { | ||
decode(types: Array<string | ParamType>, data: BytesLike, loose?: boolean): Result { | ||
decode(types: ReadonlyArray<string | ParamType>, data: BytesLike, loose?: boolean): Result { | ||
const coders: Array<Coder> = types.map((type) => this._getCoder(ParamType.from(type))); | ||
@@ -122,0 +121,0 @@ const coder = new TupleCoder(coders, "_"); |
@@ -20,3 +20,3 @@ "use strict"; | ||
try { | ||
getAddress(value); | ||
value = getAddress(value) | ||
} catch (error) { | ||
@@ -23,0 +23,0 @@ this._throwError(error.message, value); |
@@ -147,2 +147,3 @@ "use strict"; | ||
Object.defineProperty(values, name, { | ||
enumerable: true, | ||
get: () => { throw value; } | ||
@@ -159,2 +160,3 @@ }); | ||
Object.defineProperty(values, i, { | ||
enumerable: true, | ||
get: () => { throw value; } | ||
@@ -217,4 +219,15 @@ }); | ||
count = reader.readValue().toNumber(); | ||
// Check that there is *roughly* enough data to ensure | ||
// stray random data is not being read as a length. Each | ||
// slot requires at least 32 bytes for their value (or 32 | ||
// bytes as a link to the data). This could use a much | ||
// tighter bound, but we are erroring on the side of safety. | ||
if (count * 32 > reader._data.length) { | ||
logger.throwError("insufficient data length", Logger.errors.BUFFER_OVERRUN, { | ||
length: reader._data.length, | ||
count: count | ||
}); | ||
} | ||
} | ||
let coders = []; | ||
@@ -221,0 +234,0 @@ for (let i = 0; i < count; i++) { coders.push(new AnonymousCoder(this.coder)); } |
@@ -11,25 +11,25 @@ "use strict"; | ||
export interface JsonFragmentType { | ||
name?: string; | ||
indexed?: boolean; | ||
type?: string; | ||
components?: Array<JsonFragmentType>; | ||
readonly name?: string; | ||
readonly indexed?: boolean; | ||
readonly type?: string; | ||
readonly internalType?: any; // @TODO: in v6 reduce type | ||
readonly components?: ReadonlyArray<JsonFragmentType>; | ||
} | ||
export interface JsonFragment { | ||
name?: string; | ||
type?: string; | ||
readonly name?: string; | ||
readonly type?: string; | ||
anonymous?: boolean; | ||
readonly anonymous?: boolean; | ||
payable?: boolean; | ||
constant?: boolean; | ||
stateMutability?: string; | ||
readonly payable?: boolean; | ||
readonly constant?: boolean; | ||
readonly stateMutability?: string; | ||
inputs?: Array<JsonFragmentType>; | ||
outputs?: Array<JsonFragmentType>; | ||
readonly inputs?: ReadonlyArray<JsonFragmentType>; | ||
readonly outputs?: ReadonlyArray<JsonFragmentType>; | ||
gas?: string; | ||
readonly gas?: string; | ||
}; | ||
const _constructorGuard = { }; | ||
@@ -243,3 +243,3 @@ | ||
// Human-Readble with nice spacing, including all names | ||
// Human-Readable with nice spacing, including all names | ||
full: "full", | ||
@@ -311,3 +311,3 @@ | ||
// - minimal: "tuple(uint256,address) indexed" | ||
// - full: "tuple(uint256 foo, addres bar) indexed baz" | ||
// - full: "tuple(uint256 foo, address bar) indexed baz" | ||
format(format?: string): string { | ||
@@ -405,3 +405,3 @@ if (!format) { format = FormatTypes.sighash; } | ||
readonly name: string; | ||
readonly inputs: Array<ParamType>; | ||
readonly inputs: ReadonlyArray<ParamType>; | ||
} | ||
@@ -452,2 +452,4 @@ | ||
return ConstructorFragment.fromObject(value); | ||
case "error": | ||
return ErrorFragment.fromObject(value); | ||
case "fallback": | ||
@@ -474,2 +476,4 @@ case "receive": | ||
return ConstructorFragment.fromString(value.trim()); | ||
} else if (value.split(" ")[0] === "error") { | ||
return ErrorFragment.fromString(value.substring(5).trim()); | ||
} | ||
@@ -936,8 +940,86 @@ | ||
//export class ErrorFragment extends Fragment { | ||
//} | ||
//export class StructFragment extends Fragment { | ||
//} | ||
function checkForbidden(fragment: ErrorFragment): ErrorFragment { | ||
const sig = fragment.format(); | ||
if (sig === "Error(string)" || sig === "Panic(uint256)") { | ||
logger.throwArgumentError(`cannot specify user defined ${ sig } error`, "fragment", fragment); | ||
} | ||
return fragment; | ||
} | ||
export class ErrorFragment extends Fragment { | ||
format(format?: string): string { | ||
if (!format) { format = FormatTypes.sighash; } | ||
if (!FormatTypes[format]) { | ||
logger.throwArgumentError("invalid format type", "format", format); | ||
} | ||
if (format === FormatTypes.json) { | ||
return JSON.stringify({ | ||
type: "error", | ||
name: this.name, | ||
inputs: this.inputs.map((input) => JSON.parse(input.format(format))), | ||
}); | ||
} | ||
let result = ""; | ||
if (format !== FormatTypes.sighash) { | ||
result += "error "; | ||
} | ||
result += this.name + "(" + this.inputs.map( | ||
(input) => input.format(format) | ||
).join((format === FormatTypes.full) ? ", ": ",") + ") "; | ||
return result.trim(); | ||
} | ||
static from(value: ErrorFragment | JsonFragment | string): ErrorFragment { | ||
if (typeof(value) === "string") { | ||
return ErrorFragment.fromString(value); | ||
} | ||
return ErrorFragment.fromObject(value); | ||
} | ||
static fromObject(value: ErrorFragment | JsonFragment): ErrorFragment { | ||
if (ErrorFragment.isErrorFragment(value)) { return value; } | ||
if (value.type !== "error") { | ||
logger.throwArgumentError("invalid error object", "value", value); | ||
} | ||
const params: TypeCheck<_Fragment> = { | ||
type: value.type, | ||
name: verifyIdentifier(value.name), | ||
inputs: (value.inputs ? value.inputs.map(ParamType.fromObject): []) | ||
}; | ||
return checkForbidden(new ErrorFragment(_constructorGuard, params)); | ||
} | ||
static fromString(value: string): ErrorFragment { | ||
let params: any = { type: "error" }; | ||
let parens = value.match(regexParen); | ||
if (!parens) { | ||
logger.throwArgumentError("invalid error signature", "value", value); | ||
} | ||
params.name = parens[1].trim(); | ||
if (params.name) { verifyIdentifier(params.name); } | ||
params.inputs = parseParams(parens[2], false); | ||
return checkForbidden(ErrorFragment.fromObject(params)); | ||
} | ||
static isErrorFragment(value: any): value is ErrorFragment { | ||
return (value && value._isFragment && value.type === "error"); | ||
} | ||
} | ||
function verifyType(type: string): string { | ||
@@ -957,3 +1039,4 @@ | ||
const regexIdentifier = new RegExp("^[A-Za-z_][A-Za-z0-9_]*$"); | ||
// See: https://github.com/ethereum/solidity/blob/1f8f1a3db93a548d0555e3e14cfc55a10e25b60e/docs/grammar/SolidityLexer.g4#L234 | ||
const regexIdentifier = new RegExp("^[a-zA-Z$_][a-zA-Z0-9$_]*$"); | ||
function verifyIdentifier(value: string): string { | ||
@@ -960,0 +1043,0 @@ if (!value || !value.match(regexIdentifier)) { |
"use strict"; | ||
import { ConstructorFragment, EventFragment, FormatTypes, Fragment, FunctionFragment, JsonFragment, JsonFragmentType, ParamType } from "./fragments"; | ||
import { ConstructorFragment, ErrorFragment, EventFragment, FormatTypes, Fragment, FunctionFragment, JsonFragment, JsonFragmentType, ParamType } from "./fragments"; | ||
import { AbiCoder, CoerceFunc, defaultAbiCoder } from "./abi-coder"; | ||
@@ -9,2 +9,3 @@ import { checkResultErrors, Indexed, Interface, LogDescription, Result, TransactionDescription } from "./interface"; | ||
ConstructorFragment, | ||
ErrorFragment, | ||
EventFragment, | ||
@@ -11,0 +12,0 @@ Fragment, |
@@ -12,3 +12,3 @@ "use strict"; | ||
import { checkResultErrors, Result } from "./coders/abstract-coder"; | ||
import { ConstructorFragment, EventFragment, FormatTypes, Fragment, FunctionFragment, JsonFragment, ParamType } from "./fragments"; | ||
import { ConstructorFragment, ErrorFragment, EventFragment, FormatTypes, Fragment, FunctionFragment, JsonFragment, ParamType } from "./fragments"; | ||
@@ -38,2 +38,10 @@ import { Logger } from "@ethersproject/logger"; | ||
export class ErrorDescription extends Description<ErrorDescription> { | ||
readonly errorFragment: ErrorFragment; | ||
readonly name: string; | ||
readonly args: Result; | ||
readonly signature: string; | ||
readonly sighash: string; | ||
} | ||
export class Indexed extends Description<Indexed> { | ||
@@ -48,2 +56,7 @@ readonly hash: string; | ||
const BuiltinErrors: Record<string, { signature: string, inputs: Array<string>, name: string, reason?: boolean }> = { | ||
"0x08c379a0": { signature: "Error(string)", name: "Error", inputs: [ "string" ], reason: true }, | ||
"0x4e487b71": { signature: "Panic(uint256)", name: "Panic", inputs: [ "uint256" ] } | ||
} | ||
function wrapAccessError(property: string, error: Error): Error { | ||
@@ -69,5 +82,5 @@ const wrap = new Error(`deferred error during ABI decoding triggered accessing ${ property }`); | ||
export class Interface { | ||
readonly fragments: Array<Fragment>; | ||
readonly fragments: ReadonlyArray<Fragment>; | ||
readonly errors: { [ name: string ]: any }; | ||
readonly errors: { [ name: string ]: ErrorFragment }; | ||
readonly events: { [ name: string ]: EventFragment }; | ||
@@ -83,6 +96,4 @@ readonly functions: { [ name: string ]: FunctionFragment }; | ||
constructor(fragments: string | Array<Fragment | JsonFragment | string>) { | ||
logger.checkNew(new.target, Interface); | ||
let abi: Array<Fragment | JsonFragment | string> = [ ]; | ||
constructor(fragments: string | ReadonlyArray<Fragment | JsonFragment | string>) { | ||
let abi: ReadonlyArray<Fragment | JsonFragment | string> = [ ]; | ||
if (typeof(fragments) === "string") { | ||
@@ -126,2 +137,5 @@ abi = JSON.parse(fragments); | ||
break; | ||
case "error": | ||
bucket = this.errors; | ||
break; | ||
default: | ||
@@ -176,4 +190,4 @@ return; | ||
static getSighash(functionFragment: FunctionFragment): string { | ||
return hexDataSlice(id(functionFragment.format()), 0, 4); | ||
static getSighash(fragment: ErrorFragment | FunctionFragment): string { | ||
return hexDataSlice(id(fragment.format()), 0, 4); | ||
} | ||
@@ -209,3 +223,3 @@ | ||
// Normlize the signature and lookup the function | ||
// Normalize the signature and lookup the function | ||
const result = this.functions[FunctionFragment.fromString(nameOrSignatureOrSighash).format()]; | ||
@@ -243,3 +257,3 @@ if (!result) { | ||
// Normlize the signature and lookup the function | ||
// Normalize the signature and lookup the function | ||
const result = this.events[EventFragment.fromString(nameOrSignatureOrTopic).format()]; | ||
@@ -252,9 +266,51 @@ if (!result) { | ||
// Find a function definition by any means necessary (unless it is ambiguous) | ||
getError(nameOrSignatureOrSighash: string): ErrorFragment { | ||
if (isHexString(nameOrSignatureOrSighash)) { | ||
const getSighash = getStatic<(f: ErrorFragment | FunctionFragment) => string>(this.constructor, "getSighash"); | ||
for (const name in this.errors) { | ||
const error = this.errors[name]; | ||
if (nameOrSignatureOrSighash === getSighash(error)) { | ||
return this.errors[name]; | ||
} | ||
} | ||
logger.throwArgumentError("no matching error", "sighash", nameOrSignatureOrSighash); | ||
} | ||
// It is a bare name, look up the function (will return null if ambiguous) | ||
if (nameOrSignatureOrSighash.indexOf("(") === -1) { | ||
const name = nameOrSignatureOrSighash.trim(); | ||
const matching = Object.keys(this.errors).filter((f) => (f.split("("/* fix:) */)[0] === name)); | ||
if (matching.length === 0) { | ||
logger.throwArgumentError("no matching error", "name", name); | ||
} else if (matching.length > 1) { | ||
logger.throwArgumentError("multiple matching errors", "name", name); | ||
} | ||
return this.errors[matching[0]]; | ||
} | ||
// Normalize the signature and lookup the function | ||
const result = this.errors[FunctionFragment.fromString(nameOrSignatureOrSighash).format()]; | ||
if (!result) { | ||
logger.throwArgumentError("no matching error", "signature", nameOrSignatureOrSighash); | ||
} | ||
return result; | ||
} | ||
// Get the sighash (the bytes4 selector) used by Solidity to identify a function | ||
getSighash(functionFragment: FunctionFragment | string): string { | ||
if (typeof(functionFragment) === "string") { | ||
functionFragment = this.getFunction(functionFragment); | ||
getSighash(fragment: ErrorFragment | FunctionFragment | string): string { | ||
if (typeof(fragment) === "string") { | ||
try { | ||
fragment = this.getFunction(fragment); | ||
} catch (error) { | ||
try { | ||
fragment = this.getError(<string>fragment); | ||
} catch (_) { | ||
throw error; | ||
} | ||
} | ||
} | ||
return getStatic<(f: FunctionFragment) => string>(this.constructor, "getSighash")(functionFragment); | ||
return getStatic<(f: ErrorFragment | FunctionFragment) => string>(this.constructor, "getSighash")(fragment); | ||
} | ||
@@ -272,14 +328,39 @@ | ||
_decodeParams(params: Array<ParamType>, data: BytesLike): Result { | ||
_decodeParams(params: ReadonlyArray<ParamType>, data: BytesLike): Result { | ||
return this._abiCoder.decode(params, data) | ||
} | ||
_encodeParams(params: Array<ParamType>, values: Array<any>): string { | ||
_encodeParams(params: ReadonlyArray<ParamType>, values: ReadonlyArray<any>): string { | ||
return this._abiCoder.encode(params, values) | ||
} | ||
encodeDeploy(values?: Array<any>): string { | ||
encodeDeploy(values?: ReadonlyArray<any>): string { | ||
return this._encodeParams(this.deploy.inputs, values || [ ]); | ||
} | ||
decodeErrorResult(fragment: ErrorFragment | string, data: BytesLike): Result { | ||
if (typeof(fragment) === "string") { | ||
fragment = this.getError(fragment); | ||
} | ||
const bytes = arrayify(data); | ||
if (hexlify(bytes.slice(0, 4)) !== this.getSighash(fragment)) { | ||
logger.throwArgumentError(`data signature does not match error ${ fragment.name }.`, "data", hexlify(bytes)); | ||
} | ||
return this._decodeParams(fragment.inputs, bytes.slice(4)); | ||
} | ||
encodeErrorResult(fragment: ErrorFragment | string, values?: ReadonlyArray<any>): string { | ||
if (typeof(fragment) === "string") { | ||
fragment = this.getError(fragment); | ||
} | ||
return hexlify(concat([ | ||
this.getSighash(fragment), | ||
this._encodeParams(fragment.inputs, values || [ ]) | ||
])); | ||
} | ||
// Decode the data for a function call (e.g. tx.data) | ||
@@ -301,3 +382,3 @@ decodeFunctionData(functionFragment: FunctionFragment | string, data: BytesLike): Result { | ||
// Encode the data for a function call (e.g. tx.data) | ||
encodeFunctionData(functionFragment: FunctionFragment | string, values?: Array<any>): string { | ||
encodeFunctionData(functionFragment: FunctionFragment | string, values?: ReadonlyArray<any>): string { | ||
if (typeof(functionFragment) === "string") { | ||
@@ -319,5 +400,8 @@ functionFragment = this.getFunction(functionFragment); | ||
let bytes = arrayify(data); | ||
let bytes = arrayify(data); | ||
let reason: string = null; | ||
let message = ""; | ||
let errorArgs: Result = null; | ||
let errorName: string = null; | ||
let errorSignature: string = null; | ||
@@ -331,15 +415,30 @@ switch (bytes.length % this._abiCoder._getWordSize()) { | ||
case 4: | ||
if (hexlify(bytes.slice(0, 4)) === "0x08c379a0") { | ||
errorSignature = "Error(string)"; | ||
reason = this._abiCoder.decode([ "string" ], bytes.slice(4))[0]; | ||
case 4: { | ||
const selector = hexlify(bytes.slice(0, 4)); | ||
const builtin = BuiltinErrors[selector]; | ||
if (builtin) { | ||
errorArgs = this._abiCoder.decode(builtin.inputs, bytes.slice(4)); | ||
errorName = builtin.name; | ||
errorSignature = builtin.signature; | ||
if (builtin.reason) { reason = errorArgs[0]; } | ||
if (errorName === "Error") { | ||
message = `; VM Exception while processing transaction: reverted with reason string ${ JSON.stringify(errorArgs[0]) }`; | ||
} else if (errorName === "Panic") { | ||
message = `; VM Exception while processing transaction: reverted with panic code ${ errorArgs[0] }`; | ||
} | ||
} else { | ||
try { | ||
const error = this.getError(selector); | ||
errorArgs = this._abiCoder.decode(error.inputs, bytes.slice(4)); | ||
errorName = error.name; | ||
errorSignature = error.format(); | ||
} catch (error) { } | ||
} | ||
break; | ||
} | ||
} | ||
return logger.throwError("call revert exception", Logger.errors.CALL_EXCEPTION, { | ||
return logger.throwError("call revert exception" + message, Logger.errors.CALL_EXCEPTION, { | ||
method: functionFragment.format(), | ||
errorSignature: errorSignature, | ||
errorArgs: [ reason ], | ||
reason: reason | ||
data: hexlify(data), errorArgs, errorName, errorSignature, reason | ||
}); | ||
@@ -349,3 +448,3 @@ } | ||
// Encode the result for a function call (e.g. for eth_call) | ||
encodeFunctionResult(functionFragment: FunctionFragment | string, values?: Array<any>): string { | ||
encodeFunctionResult(functionFragment: FunctionFragment | string, values?: ReadonlyArray<any>): string { | ||
if (typeof(functionFragment) === "string") { | ||
@@ -359,3 +458,3 @@ functionFragment = this.getFunction(functionFragment); | ||
// Create the filter for the event with search criteria (e.g. for eth_filterLog) | ||
encodeFilterTopics(eventFragment: EventFragment, values: Array<any>): Array<string | Array<string>> { | ||
encodeFilterTopics(eventFragment: EventFragment | string, values: ReadonlyArray<any>): Array<string | Array<string>> { | ||
if (typeof(eventFragment) === "string") { | ||
@@ -382,2 +481,10 @@ eventFragment = this.getEvent(eventFragment); | ||
if (param.type === "bool" && typeof(value) === "boolean") { | ||
value = (value ? "0x01": "0x00"); | ||
} | ||
if (param.type.match(/^u?int/)) { | ||
value = BigNumber.from(value).toHexString(); | ||
} | ||
// Check addresses are valid | ||
@@ -390,3 +497,3 @@ if (param.type === "address") { this._abiCoder.encode( [ "address" ], [ value ]); } | ||
let param = eventFragment.inputs[index]; | ||
let param = (<EventFragment>eventFragment).inputs[index]; | ||
@@ -419,3 +526,3 @@ if (!param.indexed) { | ||
encodeEventLog(eventFragment: EventFragment, values: Array<any>): { data: string, topics: Array<string> } { | ||
encodeEventLog(eventFragment: EventFragment | string, values: ReadonlyArray<any>): { data: string, topics: Array<string> } { | ||
if (typeof(eventFragment) === "string") { | ||
@@ -446,3 +553,3 @@ eventFragment = this.getEvent(eventFragment); | ||
} else if (param.baseType === "tuple" || param.baseType === "array") { | ||
// @TOOD | ||
// @TODO | ||
throw new Error("not implemented"); | ||
@@ -465,3 +572,3 @@ } else { | ||
// Decode a filter for the event and the search criteria | ||
decodeEventLog(eventFragment: EventFragment | string, data: BytesLike, topics?: Array<string>): Result { | ||
decodeEventLog(eventFragment: EventFragment | string, data: BytesLike, topics?: ReadonlyArray<string>): Result { | ||
if (typeof(eventFragment) === "string") { | ||
@@ -533,2 +640,3 @@ eventFragment = this.getEvent(eventFragment); | ||
Object.defineProperty(result, param.name, { | ||
enumerable: true, | ||
get: () => { throw wrapAccessError(`property ${ JSON.stringify(param.name) }`, value); } | ||
@@ -547,2 +655,3 @@ }); | ||
Object.defineProperty(result, i, { | ||
enumerable: true, | ||
get: () => { throw wrapAccessError(`index ${ i }`, value); } | ||
@@ -573,2 +682,5 @@ }); | ||
// @TODO | ||
//parseCallResult(data: BytesLike): ?? | ||
// Given an event log, find the matching event fragment (if any) and | ||
@@ -583,3 +695,3 @@ // determine all its properties and values | ||
// Probably not, because just because it is the only event in the ABI does | ||
// not mean we have the full ABI; maybe jsut a fragment? | ||
// not mean we have the full ABI; maybe just a fragment? | ||
@@ -596,3 +708,18 @@ | ||
parseError(data: BytesLike): ErrorDescription { | ||
const hexData = hexlify(data); | ||
let fragment = this.getError(hexData.substring(0, 10).toLowerCase()) | ||
if (!fragment) { return null; } | ||
return new ErrorDescription({ | ||
args: this._abiCoder.decode(fragment.inputs, "0x" + hexData.substring(10)), | ||
errorFragment: fragment, | ||
name: fragment.name, | ||
signature: fragment.format(), | ||
sighash: this.getSighash(fragment), | ||
}); | ||
} | ||
/* | ||
@@ -599,0 +726,0 @@ static from(value: Array<Fragment | string | JsonAbi> | string | Interface) { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
497890
7532
Updated@ethersproject/bytes@^5.7.0
Updated@ethersproject/hash@^5.7.0
Updated@ethersproject/logger@^5.7.0