Skip to content
This repository has been archived by the owner on Jul 9, 2021. It is now read-only.

Handle ABI decoding NULL for all data types #1587

Merged
merged 5 commits into from
Feb 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/utils/CHANGELOG.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
[
{
"version": "4.0.2",
"changes": [
{
"note": "ABI Decode NULL for all data types",
"pr": 1587
}
]
},
{
"version": "4.0.1",
"changes": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ export abstract class DataType {
const hasSelector = !_.isUndefined(selector);
const rawCalldata = new RawCalldata(calldata, hasSelector);
const rules_ = _.isUndefined(rules) ? constants.DEFAULT_DECODING_RULES : rules;
const value = this.generateValue(rawCalldata, rules_);
const value =
rawCalldata.getSizeInBytes() > 0 ? this.generateValue(rawCalldata, rules_) : this.getDefaultValue(rules_);
return value;
}

Expand All @@ -71,6 +72,7 @@ export abstract class DataType {

public abstract generateCalldataBlock(value: any, parentBlock?: CalldataBlock): CalldataBlock;
public abstract generateValue(calldata: RawCalldata, rules: DecodingRules): any;
public abstract getDefaultValue(rules?: DecodingRules): any;
public abstract getSignatureType(): string;
public abstract isStatic(): boolean;
}
21 changes: 21 additions & 0 deletions packages/utils/src/abi_encoder/abstract_data_types/types/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,27 @@ export abstract class AbstractSetDataType extends DataType {
return isStatic;
}

public getDefaultValue(rules?: DecodingRules): any[] | object {
let defaultValue: any[] | object;
if (this._isArray && _.isUndefined(this._arrayLength)) {
defaultValue = [];
} else if (!_.isUndefined(rules) && rules.shouldConvertStructsToObjects && !this._isArray) {
defaultValue = {};
_.each(this._memberIndexByName, (idx: number, key: string) => {
const member = this._members[idx];
const memberValue = member.getDefaultValue();
(defaultValue as { [key: string]: any })[key] = memberValue;
});
} else {
defaultValue = [];
_.each(this._members, (member: DataType, idx: number) => {
const memberValue = member.getDefaultValue();
(defaultValue as any[]).push(memberValue);
});
}
return defaultValue;
}

protected _generateCalldataBlockFromArray(value: any[], parentBlock?: CalldataBlock): SetCalldataBlock {
// Sanity check: if the set has a defined length then `value` must have the same length.
if (!_.isUndefined(this._arrayLength) && value.length !== this._arrayLength) {
Expand Down
5 changes: 5 additions & 0 deletions packages/utils/src/abi_encoder/calldata/raw_calldata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,9 @@ export class RawCalldata {
public getSelector(): string {
return this._selector;
}

public getSizeInBytes(): number {
const sizeInBytes = this._value.byteLength;
return sizeInBytes;
}
}
5 changes: 5 additions & 0 deletions packages/utils/src/abi_encoder/evm_data_types/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export class AddressDataType extends AbstractBlobDataType {
private static readonly _ADDRESS_SIZE_IN_BYTES = 20;
private static readonly _DECODED_ADDRESS_OFFSET_IN_BYTES =
constants.EVM_WORD_WIDTH_IN_BYTES - AddressDataType._ADDRESS_SIZE_IN_BYTES;
private static readonly _DEFAULT_VALUE = '0x0000000000000000000000000000000000000000';

public static matchType(type: string): boolean {
return type === SolidityTypes.Address;
Expand Down Expand Up @@ -43,6 +44,10 @@ export class AddressDataType extends AbstractBlobDataType {
return valueLowercase;
}

public getDefaultValue(): string {
return AddressDataType._DEFAULT_VALUE;
}

public getSignatureType(): string {
return SolidityTypes.Address;
}
Expand Down
5 changes: 5 additions & 0 deletions packages/utils/src/abi_encoder/evm_data_types/bool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { constants } from '../utils/constants';

export class BoolDataType extends AbstractBlobDataType {
private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true;
private static readonly _DEFAULT_VALUE: boolean = false;

public static matchType(type: string): boolean {
return type === SolidityTypes.Bool;
Expand Down Expand Up @@ -47,6 +48,10 @@ export class BoolDataType extends AbstractBlobDataType {
return value;
}

public getDefaultValue(): boolean {
return BoolDataType._DEFAULT_VALUE;
}

public getSignatureType(): string {
return SolidityTypes.Bool;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { constants } from '../utils/constants';

export class DynamicBytesDataType extends AbstractBlobDataType {
private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = false;
private static readonly _DEFAULT_VALUE = '0x';

public static matchType(type: string): boolean {
return type === SolidityTypes.Bytes;
Expand Down Expand Up @@ -65,6 +66,10 @@ export class DynamicBytesDataType extends AbstractBlobDataType {
return value;
}

public getDefaultValue(): string {
return DynamicBytesDataType._DEFAULT_VALUE;
}

public getSignatureType(): string {
return SolidityTypes.Bytes;
}
Expand Down
12 changes: 10 additions & 2 deletions packages/utils/src/abi_encoder/evm_data_types/int.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export class IntDataType extends AbstractBlobDataType {
private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true;
private static readonly _MAX_WIDTH: number = 256;
private static readonly _DEFAULT_WIDTH: number = IntDataType._MAX_WIDTH;
private static readonly _DEFAULT_VALUE = new BigNumber(0);
private readonly _width: number;
private readonly _minValue: BigNumber;
private readonly _maxValue: BigNumber;
Expand Down Expand Up @@ -50,13 +51,20 @@ export class IntDataType extends AbstractBlobDataType {
public decodeValue(calldata: RawCalldata): BigNumber | number {
const valueBuf = calldata.popWord();
const value = EncoderMath.safeDecodeNumericValue(valueBuf, this._minValue, this._maxValue);
const numberOfBytesInUint8 = 8;
if (this._width === numberOfBytesInUint8) {
if (this._width === constants.NUMBER_OF_BYTES_IN_INT8) {
return value.toNumber();
}
return value;
}

public getDefaultValue(): BigNumber | number {
const defaultValue = IntDataType._DEFAULT_VALUE;
if (this._width === constants.NUMBER_OF_BYTES_IN_INT8) {
return defaultValue.toNumber();
}
return defaultValue;
}

public getSignatureType(): string {
return `${SolidityTypes.Int}${this._width}`;
}
Expand Down
5 changes: 5 additions & 0 deletions packages/utils/src/abi_encoder/evm_data_types/pointer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,9 @@ export class PointerDataType extends AbstractPointerDataType {
public getSignature(isDetailed?: boolean): string {
return this._destination.getSignature(isDetailed);
}

public getDefaultValue(): any {
const defaultValue = this._destination.getDefaultValue();
return defaultValue;
}
}
7 changes: 7 additions & 0 deletions packages/utils/src/abi_encoder/evm_data_types/static_bytes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ export class StaticBytesDataType extends AbstractBlobDataType {
return value;
}

public getDefaultValue(): string {
const valueBufPadded = constants.EMPTY_EVM_WORD_BUFFER;
const valueBuf = valueBufPadded.slice(0, this._width);
const value = ethUtil.bufferToHex(valueBuf);
return value;
}

private _sanityCheckValue(value: string | Buffer): void {
if (typeof value === 'string') {
if (!_.startsWith(value, '0x')) {
Expand Down
5 changes: 5 additions & 0 deletions packages/utils/src/abi_encoder/evm_data_types/string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { constants } from '../utils/constants';

export class StringDataType extends AbstractBlobDataType {
private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = false;
private static readonly _DEFAULT_VALUE = '';

public static matchType(type: string): boolean {
return type === SolidityTypes.String;
Expand Down Expand Up @@ -52,6 +53,10 @@ export class StringDataType extends AbstractBlobDataType {
return value;
}

public getDefaultValue(): string {
return StringDataType._DEFAULT_VALUE;
}

public getSignatureType(): string {
return SolidityTypes.String;
}
Expand Down
12 changes: 10 additions & 2 deletions packages/utils/src/abi_encoder/evm_data_types/uint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export class UIntDataType extends AbstractBlobDataType {
private static readonly _MAX_WIDTH: number = 256;
private static readonly _DEFAULT_WIDTH: number = UIntDataType._MAX_WIDTH;
private static readonly _MIN_VALUE = new BigNumber(0);
private static readonly _DEFAULT_VALUE = new BigNumber(0);
private readonly _width: number;
private readonly _maxValue: BigNumber;

Expand Down Expand Up @@ -49,13 +50,20 @@ export class UIntDataType extends AbstractBlobDataType {
public decodeValue(calldata: RawCalldata): BigNumber | number {
const valueBuf = calldata.popWord();
const value = EncoderMath.safeDecodeNumericValue(valueBuf, UIntDataType._MIN_VALUE, this._maxValue);
const numberOfBytesInUint8 = 8;
if (this._width === numberOfBytesInUint8) {
if (this._width === constants.NUMBER_OF_BYTES_IN_UINT8) {
return value.toNumber();
}
return value;
}

public getDefaultValue(): BigNumber | number {
const defaultValue = UIntDataType._DEFAULT_VALUE;
if (this._width === constants.NUMBER_OF_BYTES_IN_UINT8) {
return defaultValue.toNumber();
}
return defaultValue;
}

public getSignatureType(): string {
return `${SolidityTypes.Uint}${this._width}`;
}
Expand Down
6 changes: 6 additions & 0 deletions packages/utils/src/abi_encoder/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as ethUtil from 'ethereumjs-util';

import { DecodingRules, EncodingRules } from './rules';

export const constants = {
Expand All @@ -14,4 +16,8 @@ export const constants = {
DEFAULT_DECODING_RULES: { shouldConvertStructsToObjects: true } as DecodingRules,
DEFAULT_ENCODING_RULES: { shouldOptimize: true, shouldAnnotate: false } as EncodingRules,
/* tslint:enable no-object-literal-type-assertion */
EMPTY_EVM_WORD_STRING: '0x0000000000000000000000000000000000000000000000000000000000000000',
EMPTY_EVM_WORD_BUFFER: ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000000'),
NUMBER_OF_BYTES_IN_UINT8: 8,
NUMBER_OF_BYTES_IN_INT8: 8,
};
25 changes: 25 additions & 0 deletions packages/utils/test/abi_encoder/abi_samples/return_value_abis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,28 @@ export const mixedStaticAndDynamicReturnValues: MethodAbi = {
stateMutability: 'nonpayable',
type: 'function',
};

export const structuredReturnValue: MethodAbi = {
constant: false,
inputs: [],
name: 'fillOrder',
outputs: [
{
components: [
{
name: 'makerAssetFilledAmount',
type: 'uint256',
},
{
name: 'takerAssetFilledAmount',
type: 'uint256',
},
],
name: 'fillResults',
type: 'tuple',
},
],
payable: false,
stateMutability: 'nonpayable',
type: 'function',
};
Loading