aboutsummaryrefslogtreecommitdiffstats
path: root/packages/utils/src
diff options
context:
space:
mode:
authorGreg Hysen <greg.hysen@gmail.com>2018-12-20 05:01:22 +0800
committerGreg Hysen <greg.hysen@gmail.com>2019-01-15 02:49:44 +0800
commite9a82905e35041d36c4c9be75e11c0399ee96b89 (patch)
treebd49ab279ae96fb0248b252e55399f3ce50c4793 /packages/utils/src
parentf8684d6a776724d0172c30126a7277885ed4e966 (diff)
downloaddexon-0x-contracts-e9a82905e35041d36c4c9be75e11c0399ee96b89.tar.gz
dexon-0x-contracts-e9a82905e35041d36c4c9be75e11c0399ee96b89.tar.zst
dexon-0x-contracts-e9a82905e35041d36c4c9be75e11c0399ee96b89.zip
Abi Encoder tests fixed + added a signature parser for cases where MethodAbi/DataItems are not readily available
Diffstat (limited to 'packages/utils/src')
-rw-r--r--packages/utils/src/abi_encoder/abstract_data_types/data_type.ts10
-rw-r--r--packages/utils/src/abi_encoder/abstract_data_types/types/set.ts4
-rw-r--r--packages/utils/src/abi_encoder/evm_data_types/address.ts2
-rw-r--r--packages/utils/src/abi_encoder/evm_data_types/array.ts18
-rw-r--r--packages/utils/src/abi_encoder/evm_data_types/bool.ts2
-rw-r--r--packages/utils/src/abi_encoder/evm_data_types/dynamic_bytes.ts2
-rw-r--r--packages/utils/src/abi_encoder/evm_data_types/int.ts2
-rw-r--r--packages/utils/src/abi_encoder/evm_data_types/method.ts2
-rw-r--r--packages/utils/src/abi_encoder/evm_data_types/pointer.ts8
-rw-r--r--packages/utils/src/abi_encoder/evm_data_types/static_bytes.ts2
-rw-r--r--packages/utils/src/abi_encoder/evm_data_types/string.ts2
-rw-r--r--packages/utils/src/abi_encoder/evm_data_types/tuple.ts17
-rw-r--r--packages/utils/src/abi_encoder/evm_data_types/uint.ts2
-rw-r--r--packages/utils/src/abi_encoder/index.ts1
-rw-r--r--packages/utils/src/abi_encoder/utils/signatureParser.ts154
15 files changed, 206 insertions, 22 deletions
diff --git a/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts b/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts
index 13cc87e2a..5bd6aae03 100644
--- a/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts
+++ b/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts
@@ -51,8 +51,16 @@ export abstract class DataType {
return value;
}
+ public getSignature(detailed?: boolean): string {
+ if (_.isEmpty(this._dataItem.name) || !detailed) return this.getSignatureType();
+ const name = this.getDataItem().name;
+ const shortName = name.indexOf('.') > 0 ? name.substr(name.lastIndexOf('.') + 1) : name;
+ const detailedSignature = `${shortName} ${this.getSignatureType()}`;
+ return detailedSignature;
+ }
+
public abstract generateCalldataBlock(value: any, parentBlock?: CalldataBlock): CalldataBlock;
public abstract generateValue(calldata: RawCalldata, rules: DecodingRules): any;
- public abstract getSignature(): string;
+ public abstract getSignatureType(): string;
public abstract isStatic(): boolean;
}
diff --git a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts
index 73e9cf778..d7105ff5f 100644
--- a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts
+++ b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts
@@ -155,11 +155,11 @@ export abstract class AbstractSetDataType extends DataType {
return block;
}
- protected _computeSignatureOfMembers(): string {
+ protected _computeSignatureOfMembers(detailed?: boolean): string {
// Compute signature of members
let signature = `(`;
_.each(this._members, (member: DataType, i: number) => {
- signature += member.getSignature();
+ signature += member.getSignature(detailed);
if (i < this._members.length - 1) {
signature += ',';
}
diff --git a/packages/utils/src/abi_encoder/evm_data_types/address.ts b/packages/utils/src/abi_encoder/evm_data_types/address.ts
index 3ab823019..2278830eb 100644
--- a/packages/utils/src/abi_encoder/evm_data_types/address.ts
+++ b/packages/utils/src/abi_encoder/evm_data_types/address.ts
@@ -43,7 +43,7 @@ export class AddressDataType extends AbstractBlobDataType {
return valueLowercase;
}
- public getSignature(): string {
+ public getSignatureType(): string {
return SolidityTypes.Address;
}
/* tslint:enable prefer-function-over-method */
diff --git a/packages/utils/src/abi_encoder/evm_data_types/array.ts b/packages/utils/src/abi_encoder/evm_data_types/array.ts
index 7595cb667..8b71dc913 100644
--- a/packages/utils/src/abi_encoder/evm_data_types/array.ts
+++ b/packages/utils/src/abi_encoder/evm_data_types/array.ts
@@ -38,22 +38,30 @@ export class ArrayDataType extends AbstractSetDataType {
this._arraySignature = this._computeSignature();
}
- public getSignature(): string {
- return this._arraySignature;
+ public getSignatureType(): string {
+ return this._computeSignature(false);
}
- private _computeSignature(): string {
+ public getSignature(detailed?: boolean): string {
+ if (_.isEmpty(this.getDataItem().name) || !detailed) return this.getSignatureType();
+ const name = this.getDataItem().name;
+ const shortName = name.indexOf('.') > 0 ? name.substr(name.lastIndexOf('.') + 1) : name;
+ const detailedSignature = `${shortName} ${this._computeSignature(detailed)}`;
+ return detailedSignature;
+ }
+
+ private _computeSignature(detailed?: boolean): string {
// Compute signature for a single array element
const elementDataItem: DataItem = {
type: this._elementType,
- name: 'N/A',
+ name: '',
};
const elementComponents = this.getDataItem().components;
if (!_.isUndefined(elementComponents)) {
elementDataItem.components = elementComponents;
}
const elementDataType = this.getFactory().create(elementDataItem);
- const elementSignature = elementDataType.getSignature();
+ const elementSignature = elementDataType.getSignature(detailed);
// Construct signature for array of type `element`
if (_.isUndefined(this._arrayLength)) {
return `${elementSignature}[]`;
diff --git a/packages/utils/src/abi_encoder/evm_data_types/bool.ts b/packages/utils/src/abi_encoder/evm_data_types/bool.ts
index d713d5a94..7f91f34e6 100644
--- a/packages/utils/src/abi_encoder/evm_data_types/bool.ts
+++ b/packages/utils/src/abi_encoder/evm_data_types/bool.ts
@@ -46,7 +46,7 @@ export class BoolDataType extends AbstractBlobDataType {
return value;
}
- public getSignature(): string {
+ public getSignatureType(): string {
return SolidityTypes.Bool;
}
/* tslint:enable prefer-function-over-method */
diff --git a/packages/utils/src/abi_encoder/evm_data_types/dynamic_bytes.ts b/packages/utils/src/abi_encoder/evm_data_types/dynamic_bytes.ts
index 5277efd6c..fa38b63c0 100644
--- a/packages/utils/src/abi_encoder/evm_data_types/dynamic_bytes.ts
+++ b/packages/utils/src/abi_encoder/evm_data_types/dynamic_bytes.ts
@@ -65,7 +65,7 @@ export class DynamicBytesDataType extends AbstractBlobDataType {
return value;
}
- public getSignature(): string {
+ public getSignatureType(): string {
return SolidityTypes.Bytes;
}
/* tslint:enable prefer-function-over-method */
diff --git a/packages/utils/src/abi_encoder/evm_data_types/int.ts b/packages/utils/src/abi_encoder/evm_data_types/int.ts
index c9f734799..865a76545 100644
--- a/packages/utils/src/abi_encoder/evm_data_types/int.ts
+++ b/packages/utils/src/abi_encoder/evm_data_types/int.ts
@@ -56,7 +56,7 @@ export class IntDataType extends AbstractBlobDataType {
return value;
}
- public getSignature(): string {
+ public getSignatureType(): string {
return `${SolidityTypes.Int}${this._width}`;
}
}
diff --git a/packages/utils/src/abi_encoder/evm_data_types/method.ts b/packages/utils/src/abi_encoder/evm_data_types/method.ts
index bae0fdb5d..44456cd0a 100644
--- a/packages/utils/src/abi_encoder/evm_data_types/method.ts
+++ b/packages/utils/src/abi_encoder/evm_data_types/method.ts
@@ -57,7 +57,7 @@ export class MethodDataType extends AbstractSetDataType {
return returnValue;
}
- public getSignature(): string {
+ public getSignatureType(): string {
return this._methodSignature;
}
diff --git a/packages/utils/src/abi_encoder/evm_data_types/pointer.ts b/packages/utils/src/abi_encoder/evm_data_types/pointer.ts
index 389e75927..8c3afe0c3 100644
--- a/packages/utils/src/abi_encoder/evm_data_types/pointer.ts
+++ b/packages/utils/src/abi_encoder/evm_data_types/pointer.ts
@@ -11,7 +11,11 @@ export class PointerDataType extends AbstractPointerDataType {
super(dataItem, dataTypeFactory, destDataType, parentDataType);
}
- public getSignature(): string {
- return this._destination.getSignature();
+ public getSignatureType(): string {
+ return this._destination.getSignature(false);
+ }
+
+ public getSignature(detailed?: boolean): string {
+ return this._destination.getSignature(detailed);
}
}
diff --git a/packages/utils/src/abi_encoder/evm_data_types/static_bytes.ts b/packages/utils/src/abi_encoder/evm_data_types/static_bytes.ts
index 2e371c505..cbf1957d7 100644
--- a/packages/utils/src/abi_encoder/evm_data_types/static_bytes.ts
+++ b/packages/utils/src/abi_encoder/evm_data_types/static_bytes.ts
@@ -36,7 +36,7 @@ export class StaticBytesDataType extends AbstractBlobDataType {
this._width = StaticBytesDataType._decodeWidthFromType(dataItem.type);
}
- public getSignature(): string {
+ public getSignatureType(): string {
// Note that `byte` reduces to `bytes1`
return `${SolidityTypes.Bytes}${this._width}`;
}
diff --git a/packages/utils/src/abi_encoder/evm_data_types/string.ts b/packages/utils/src/abi_encoder/evm_data_types/string.ts
index 91a72ad3f..97ac46442 100644
--- a/packages/utils/src/abi_encoder/evm_data_types/string.ts
+++ b/packages/utils/src/abi_encoder/evm_data_types/string.ts
@@ -52,7 +52,7 @@ export class StringDataType extends AbstractBlobDataType {
return value;
}
- public getSignature(): string {
+ public getSignatureType(): string {
return SolidityTypes.String;
}
/* tslint:enable prefer-function-over-method */
diff --git a/packages/utils/src/abi_encoder/evm_data_types/tuple.ts b/packages/utils/src/abi_encoder/evm_data_types/tuple.ts
index 31593c882..587653f49 100644
--- a/packages/utils/src/abi_encoder/evm_data_types/tuple.ts
+++ b/packages/utils/src/abi_encoder/evm_data_types/tuple.ts
@@ -1,10 +1,11 @@
import { DataItem, SolidityTypes } from 'ethereum-types';
+import * as _ from 'lodash';
import { DataTypeFactory } from '../abstract_data_types/interfaces';
import { AbstractSetDataType } from '../abstract_data_types/types/set';
export class TupleDataType extends AbstractSetDataType {
- private readonly _signature: string;
+ //private readonly _signature: string;
public static matchType(type: string): boolean {
return type === SolidityTypes.Tuple;
@@ -15,10 +16,18 @@ export class TupleDataType extends AbstractSetDataType {
if (!TupleDataType.matchType(dataItem.type)) {
throw new Error(`Tried to instantiate Tuple with bad input: ${dataItem}`);
}
- this._signature = this._computeSignatureOfMembers();
+ //this._signature =
}
- public getSignature(): string {
- return this._signature;
+ public getSignatureType(): string {
+ return this._computeSignatureOfMembers(false);
+ }
+
+ public getSignature(detailed?: boolean): string {
+ if (_.isEmpty(this.getDataItem().name) || !detailed) return this.getSignatureType();
+ const name = this.getDataItem().name;
+ const shortName = name.indexOf('.') > 0 ? name.substr(name.lastIndexOf('.') + 1) : name;
+ const detailedSignature = `${shortName} ${this._computeSignatureOfMembers(detailed)}`;
+ return detailedSignature;
}
}
diff --git a/packages/utils/src/abi_encoder/evm_data_types/uint.ts b/packages/utils/src/abi_encoder/evm_data_types/uint.ts
index 06cde4eea..86d2705f0 100644
--- a/packages/utils/src/abi_encoder/evm_data_types/uint.ts
+++ b/packages/utils/src/abi_encoder/evm_data_types/uint.ts
@@ -55,7 +55,7 @@ export class UIntDataType extends AbstractBlobDataType {
return value;
}
- public getSignature(): string {
+ public getSignatureType(): string {
return `${SolidityTypes.Uint}${this._width}`;
}
}
diff --git a/packages/utils/src/abi_encoder/index.ts b/packages/utils/src/abi_encoder/index.ts
index baf844ac6..23422dd8b 100644
--- a/packages/utils/src/abi_encoder/index.ts
+++ b/packages/utils/src/abi_encoder/index.ts
@@ -12,3 +12,4 @@ export {
Tuple,
UInt,
} from './evm_data_type_factory';
+export { fromSignature } from './utils/signatureParser';
diff --git a/packages/utils/src/abi_encoder/utils/signatureParser.ts b/packages/utils/src/abi_encoder/utils/signatureParser.ts
new file mode 100644
index 000000000..fe5127032
--- /dev/null
+++ b/packages/utils/src/abi_encoder/utils/signatureParser.ts
@@ -0,0 +1,154 @@
+import * as _ from 'lodash';
+
+import { DataType } from '../abstract_data_types/data_type';
+import { DataItem } from 'ethereum-protocol';
+import { MethodAbi } from 'ethereum-types';
+import * as EvmDataTypes from '../evm_data_type_factory';
+
+// Valid signatures:
+// functionName(param1, param2, ...): (output1, output2, ...)
+// functionName(param1, param2, ...)
+// (param1, param2, ...)
+/*
+export function fromSignature(signature: string): DataType {
+ const maxSignatureIndex = signature.length - 1;
+ // Function name
+ const isFunction = signature.startsWith('function ');
+ // Output components
+ const outputComponentsBeginIndex = signature.indexOf(':');
+ const outputComponentsEndIndex = outputComponentsBeginIndex >= 0 ? maxSignatureIndex : 0;
+ const hasOutputComponents = outputComponentsBeginIndex >= 0;
+ const outputComponentsSignature = hasOutputComponents ? signature.substring(outputComponentsBeginIndex, outputComponentsEndIndex + 1) : "";
+ // Input components
+ const inputComponentsBeginIndex = signature.indexOf('(');
+ const inputComponentsEndIndex = hasOutputComponents ? outputComponentsBeginIndex : maxSignatureIndex;
+ const inputComponentsSignature = signature.substring(inputComponentsBeginIndex, inputComponentsEndIndex + 1);
+ // Function anme
+ const functionName = signature.substr(0, inputComponentsBeginIndex);
+ const isFunction = !_.isEmpty(functionName);
+
+ console.log(`sig - ` + inputComponentsSignature);
+ // Create data type
+ let dataType: DataType;
+ if (isFunction) {
+ const methodAbi = {
+ type: 'function',
+ name: functionName,
+ inputs: generateDataItems(inputComponentsSignature),
+ outputs: !_.isEmpty(outputComponentsSignature) ? generateDataItems(outputComponentsSignature) : [],
+ } as MethodAbi;
+ dataType = new EvmDataTypes.Method(methodAbi);
+ } else if(hasOutputComponents) {
+ throw new Error(`Invalid signature: Contains outputs but no function name.`);
+ } else {
+ const inputDataItem = generateDataItem(inputComponentsSignature);
+ console.log(JSON.stringify(inputDataItem));
+ dataType = EvmDataTypes.EvmDataTypeFactory.getInstance().create(inputDataItem);
+ }
+ return dataType;
+}*/
+
+export function fromSignature(signature: string): DataType {
+ const dataItems = generateDataItems(signature);
+ if (dataItems.length === 1) {
+ return EvmDataTypes.EvmDataTypeFactory.getInstance().create(dataItems[0]);
+ }
+ // this is a tuple
+ return EvmDataTypes.EvmDataTypeFactory.getInstance().create({
+ name: '',
+ type: 'tuple',
+ components: dataItems
+ });
+}
+
+function generateDataItems(signature: string): DataItem[] {
+ let trimmedSignature = signature;
+ if (signature.startsWith('(')) {
+ if(!signature.endsWith(')')) {
+ throw new Error(`Failed to generate data item. Must end with ')'`);
+ }
+ trimmedSignature = signature.substr(1, signature.length - 2);
+ }
+ trimmedSignature += ',';
+ let currTokenIsArray = false;
+ let currTokenArrayModifier = "";
+ let isParsingArrayModifier = false;
+ let currToken = '';
+ let parenCount = 0;
+ let currTokenName = '';
+ const dataItems: DataItem[] = [];
+ for(const char of trimmedSignature) {
+ // Tokenize the type string while keeping track of parentheses.
+ switch (char) {
+ case '(':
+ parenCount += 1;
+ currToken += char;
+ break;
+ case ')':
+ parenCount -= 1;
+ currToken += char;
+ break;
+ case '[':
+ if (parenCount === 0) {
+ isParsingArrayModifier = true;
+ currTokenIsArray = true;
+ currTokenArrayModifier += "[";
+ } else {
+ currToken += char;
+ }
+ break;
+ case ']':
+ if (parenCount === 0) {
+ isParsingArrayModifier = false;
+ currTokenArrayModifier += ']';
+ } else {
+ currToken += char;
+ }
+ break;
+ case ' ':
+ if (parenCount === 0) {
+ currTokenName = currToken;
+ currToken = "";
+ } else {
+ currToken += char;
+ }
+ break;
+ case ',':
+ if (parenCount === 0) {
+ //throw new Error(`Generating Data Items`);
+ const components = currToken.startsWith('(') ? generateDataItems(currToken) : [];
+ const isTuple = !_.isEmpty(components);
+ const isArray = currTokenIsArray;
+ let dataItem: DataItem = {name: currTokenName, type: ''};
+ if (isTuple) {
+ dataItem.type = 'tuple';
+ dataItem.components = components;
+ } else {
+ dataItem.type = currToken;
+ }
+ if (isArray) {
+ dataItem.type += currTokenArrayModifier;
+ }
+
+ dataItems.push(dataItem);
+
+ currTokenName = '';
+ currToken = '';
+ currTokenIsArray = false;
+ currTokenArrayModifier = "";
+ break;
+ } else {
+ currToken += char;
+ break;
+ }
+ default:
+ if (isParsingArrayModifier) {
+ currTokenArrayModifier += char;
+ } else {
+ currToken += char;
+ }
+ break;
+ }
+ }
+ return dataItems;
+} \ No newline at end of file