This commit is contained in:
parent
97acaa1129
commit
4e394fc680
@ -83,8 +83,8 @@ export class AbiCoder {
|
|||||||
|
|
||||||
_getWordSize(): number { return 32; }
|
_getWordSize(): number { return 32; }
|
||||||
|
|
||||||
_getReader(data: Uint8Array): Reader {
|
_getReader(data: Uint8Array, allowLoose?: boolean): Reader {
|
||||||
return new Reader(data, this._getWordSize(), this.coerceFunc);
|
return new Reader(data, this._getWordSize(), this.coerceFunc, allowLoose);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getWriter(): Writer {
|
_getWriter(): Writer {
|
||||||
@ -107,10 +107,10 @@ export class AbiCoder {
|
|||||||
return writer.data;
|
return writer.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
decode(types: Array<string | ParamType>, data: BytesLike): Result {
|
decode(types: Array<string | ParamType>, data: BytesLike, loose?: boolean): Result {
|
||||||
const coders: Array<Coder> = types.map((type) => this._getCoder(ParamType.from(type)));
|
const coders: Array<Coder> = types.map((type) => this._getCoder(ParamType.from(type)));
|
||||||
const coder = new TupleCoder(coders, "_");
|
const coder = new TupleCoder(coders, "_");
|
||||||
return coder.decode(this._getReader(arrayify(data)));
|
return coder.decode(this._getReader(arrayify(data), loose));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,16 +131,18 @@ export class Writer {
|
|||||||
|
|
||||||
export class Reader {
|
export class Reader {
|
||||||
readonly wordSize: number;
|
readonly wordSize: number;
|
||||||
|
readonly allowLoose: boolean;
|
||||||
|
|
||||||
readonly _data: Uint8Array;
|
readonly _data: Uint8Array;
|
||||||
readonly _coerceFunc: CoerceFunc;
|
readonly _coerceFunc: CoerceFunc;
|
||||||
|
|
||||||
_offset: number;
|
_offset: number;
|
||||||
|
|
||||||
constructor(data: BytesLike, wordSize?: number, coerceFunc?: CoerceFunc) {
|
constructor(data: BytesLike, wordSize?: number, coerceFunc?: CoerceFunc, allowLoose?: boolean) {
|
||||||
defineReadOnly(this, "_data", arrayify(data));
|
defineReadOnly(this, "_data", arrayify(data));
|
||||||
defineReadOnly(this, "wordSize", wordSize || 32);
|
defineReadOnly(this, "wordSize", wordSize || 32);
|
||||||
defineReadOnly(this, "_coerceFunc", coerceFunc);
|
defineReadOnly(this, "_coerceFunc", coerceFunc);
|
||||||
|
defineReadOnly(this, "allowLoose", allowLoose);
|
||||||
|
|
||||||
this._offset = 0;
|
this._offset = 0;
|
||||||
}
|
}
|
||||||
@ -160,23 +162,27 @@ export class Reader {
|
|||||||
return Reader.coerce(name, value);
|
return Reader.coerce(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
_peekBytes(offset: number, length: number): Uint8Array {
|
_peekBytes(offset: number, length: number, loose?: boolean): Uint8Array {
|
||||||
let alignedLength = Math.ceil(length / this.wordSize) * this.wordSize;
|
let alignedLength = Math.ceil(length / this.wordSize) * this.wordSize;
|
||||||
if (this._offset + alignedLength > this._data.length) {
|
if (this._offset + alignedLength > this._data.length) {
|
||||||
|
if (this.allowLoose && loose && this._offset + length <= this._data.length) {
|
||||||
|
alignedLength = length;
|
||||||
|
} else {
|
||||||
logger.throwError("data out-of-bounds", Logger.errors.BUFFER_OVERRUN, {
|
logger.throwError("data out-of-bounds", Logger.errors.BUFFER_OVERRUN, {
|
||||||
length: this._data.length,
|
length: this._data.length,
|
||||||
offset: this._offset + alignedLength
|
offset: this._offset + alignedLength
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return this._data.slice(this._offset, this._offset + alignedLength)
|
return this._data.slice(this._offset, this._offset + alignedLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
subReader(offset: number): Reader {
|
subReader(offset: number): Reader {
|
||||||
return new Reader(this._data.slice(this._offset + offset), this.wordSize, this._coerceFunc);
|
return new Reader(this._data.slice(this._offset + offset), this.wordSize, this._coerceFunc, this.allowLoose);
|
||||||
}
|
}
|
||||||
|
|
||||||
readBytes(length: number): Uint8Array {
|
readBytes(length: number, loose?: boolean): Uint8Array {
|
||||||
let bytes = this._peekBytes(0, length);
|
let bytes = this._peekBytes(0, length, !!loose);
|
||||||
this._offset += bytes.length;
|
this._offset += bytes.length;
|
||||||
// @TODO: Make sure the length..end bytes are all 0?
|
// @TODO: Make sure the length..end bytes are all 0?
|
||||||
return bytes.slice(0, length);
|
return bytes.slice(0, length);
|
||||||
|
@ -86,9 +86,6 @@ export function unpack(reader: Reader, coders: Array<Coder>): Result {
|
|||||||
// A reader anchored to this base
|
// A reader anchored to this base
|
||||||
let baseReader = reader.subReader(0);
|
let baseReader = reader.subReader(0);
|
||||||
|
|
||||||
// The amount of dynamic data read; to consume later to synchronize
|
|
||||||
let dynamicLength = 0;
|
|
||||||
|
|
||||||
coders.forEach((coder) => {
|
coders.forEach((coder) => {
|
||||||
let value: any = null;
|
let value: any = null;
|
||||||
|
|
||||||
@ -105,7 +102,6 @@ export function unpack(reader: Reader, coders: Array<Coder>): Result {
|
|||||||
value.name = coder.localName;
|
value.name = coder.localName;
|
||||||
value.type = coder.type;
|
value.type = coder.type;
|
||||||
}
|
}
|
||||||
dynamicLength += offsetReader.consumed;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@ -125,10 +121,6 @@ export function unpack(reader: Reader, coders: Array<Coder>): Result {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// @TODO: get rid of this an see if it still works?
|
|
||||||
// Consume the dynamic components in the main reader
|
|
||||||
reader.readBytes(dynamicLength);
|
|
||||||
|
|
||||||
// We only output named properties for uniquely named coders
|
// We only output named properties for uniquely named coders
|
||||||
const uniqueNames = coders.reduce((accum, coder) => {
|
const uniqueNames = coders.reduce((accum, coder) => {
|
||||||
const name = coder.localName;
|
const name = coder.localName;
|
||||||
|
@ -17,7 +17,7 @@ export class DynamicBytesCoder extends Coder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
decode(reader: Reader): any {
|
decode(reader: Reader): any {
|
||||||
return reader.readBytes(reader.readValue().toNumber());
|
return reader.readBytes(reader.readValue().toNumber(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,7 +475,7 @@ export class Interface {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let resultIndexed = (topics != null) ? this._abiCoder.decode(indexed, concat(topics)): null;
|
let resultIndexed = (topics != null) ? this._abiCoder.decode(indexed, concat(topics)): null;
|
||||||
let resultNonIndexed = this._abiCoder.decode(nonIndexed, data);
|
let resultNonIndexed = this._abiCoder.decode(nonIndexed, data, true);
|
||||||
|
|
||||||
let result: (Array<any> & { [ key: string ]: any }) = [ ];
|
let result: (Array<any> & { [ key: string ]: any }) = [ ];
|
||||||
let nonIndexedIndex = 0, indexedIndex = 0;
|
let nonIndexedIndex = 0, indexedIndex = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user