diff options
Diffstat (limited to 'packages')
14 files changed, 15 insertions, 376 deletions
diff --git a/packages/utils/src/abi_encoder/data_type.ts b/packages/utils/src/abi_encoder/data_type.ts deleted file mode 100644 index 0fbb9165a..000000000 --- a/packages/utils/src/abi_encoder/data_type.ts +++ /dev/null @@ -1,361 +0,0 @@ -import { DataItem } from 'ethereum-types'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { BigNumber } from '../configured_bignumber'; - -import * as Constants from './constants'; - -import { - Calldata, - CalldataBlock, - DependentCalldataBlock, - MemberCalldataBlock, - PayloadCalldataBlock, - RawCalldata, -} from './calldata'; - -import { DecodingRules, EncodingRules } from './utils/rules'; - -export interface DataTypeFactory { - create: (dataItem: DataItem, parentDataType?: DataType) => DataType; - mapDataItemToDataType: (dataItem: DataItem) => DataType; -} - -export interface DataTypeStaticInterface { - matchType: (type: string) => boolean; - encodeValue: (value: any) => Buffer; - decodeValue: (rawCalldata: RawCalldata) => any; -} - -export abstract class DataType { - private static readonly _DEFAULT_ENCODING_RULES: EncodingRules = { optimize: false, annotate: false }; - private static readonly _DEFAULT_DECODING_RULES: DecodingRules = { structsAsObjects: false }; - private readonly _dataItem: DataItem; - private readonly _factory: DataTypeFactory; - - constructor(dataItem: DataItem, factory: DataTypeFactory) { - this._dataItem = dataItem; - this._factory = factory; - } - - public getDataItem(): DataItem { - return this._dataItem; - } - - public getFactory(): DataTypeFactory { - return this._factory; - } - - public encode(value: any, rules?: EncodingRules, selector?: string): string { - const rules_ = rules ? rules : DataType._DEFAULT_ENCODING_RULES; - const calldata = new Calldata(rules_); - if (selector) { - calldata.setSelector(selector); - } - const block = this.generateCalldataBlock(value); - calldata.setRoot(block); // @TODO CHANGE - const calldataHex = calldata.toHexString(); - return calldataHex; - } - - public decode(calldata: string, rules?: DecodingRules, hasSelector: boolean = false): any { - const rawCalldata = new RawCalldata(calldata, hasSelector); - const rules_ = rules ? rules : DataType._DEFAULT_DECODING_RULES; - const value = this.generateValue(rawCalldata, rules_); - return value; - } - - public abstract generateCalldataBlock(value: any, parentBlock?: CalldataBlock): CalldataBlock; - public abstract generateValue(calldata: RawCalldata, rules: DecodingRules): any; - public abstract getSignature(): string; - public abstract isStatic(): boolean; -} - -export abstract class PayloadDataType extends DataType { - protected _hasConstantSize: boolean; - - public constructor(dataItem: DataItem, factory: DataTypeFactory, hasConstantSize: boolean) { - super(dataItem, factory); - this._hasConstantSize = hasConstantSize; - } - - public generateCalldataBlock(value: any, parentBlock?: CalldataBlock): PayloadCalldataBlock { - const encodedValue = this.encodeValue(value); - const name = this.getDataItem().name; - const signature = this.getSignature(); - const parentName = parentBlock === undefined ? '' : parentBlock.getName(); - const block = new PayloadCalldataBlock(name, signature, parentName, encodedValue); - return block; - } - - public generateValue(calldata: RawCalldata, rules: DecodingRules): any { - const value = this.decodeValue(calldata); - return value; - } - - public isStatic(): boolean { - return this._hasConstantSize; - } - - public abstract encodeValue(value: any): Buffer; - public abstract decodeValue(calldata: RawCalldata): any; -} - -export abstract class DependentDataType extends DataType { - protected _dependency: DataType; - protected _parent: DataType; - private readonly _isStatic: boolean; - - public constructor(dataItem: DataItem, factory: DataTypeFactory, dependency: DataType, parent: DataType) { - super(dataItem, factory); - this._dependency = dependency; - this._parent = parent; - this._isStatic = true; - } - - public generateCalldataBlock(value: any, parentBlock?: CalldataBlock): DependentCalldataBlock { - if (parentBlock === undefined) { - throw new Error(`DependentDataType requires a parent block to generate its block`); - } - const dependencyBlock = this._dependency.generateCalldataBlock(value, parentBlock); - const name = this.getDataItem().name; - const signature = this.getSignature(); - const parentName = parentBlock === undefined ? '' : parentBlock.getName(); - const block = new DependentCalldataBlock(name, signature, parentName, dependencyBlock, parentBlock); - return block; - } - - public generateValue(calldata: RawCalldata, rules: DecodingRules): any { - const destinationOffsetBuf = calldata.popWord(); - const currentOffset = calldata.getOffset(); - const destinationOffsetRelative = parseInt(ethUtil.bufferToHex(destinationOffsetBuf), Constants.HEX_BASE); - const destinationOffsetAbsolute = calldata.toAbsoluteOffset(destinationOffsetRelative); - calldata.setOffset(destinationOffsetAbsolute); - const value = this._dependency.generateValue(calldata, rules); - calldata.setOffset(currentOffset); - return value; - } - - public isStatic(): boolean { - return this._isStatic; - } -} - -export interface MemberMap { - [key: string]: number; -} - -export abstract class MemberDataType extends DataType { - protected readonly _arrayLength: number | undefined; - protected readonly _arrayElementType: string | undefined; - private readonly _memberMap: MemberMap; - private readonly _members: DataType[]; - private readonly _isArray: boolean; - - public constructor( - dataItem: DataItem, - factory: DataTypeFactory, - isArray: boolean = false, - arrayLength?: number, - arrayElementType?: string, - ) { - super(dataItem, factory); - this._memberMap = {}; - this._members = []; - this._isArray = isArray; - this._arrayLength = arrayLength; - this._arrayElementType = arrayElementType; - if (isArray && arrayLength !== undefined) { - [this._members, this._memberMap] = this._createMembersWithLength(dataItem, arrayLength); - } else if (!isArray) { - [this._members, this._memberMap] = this._createMembersWithKeys(dataItem); - } - } - - public generateCalldataBlock(value: any[] | object, parentBlock?: CalldataBlock): MemberCalldataBlock { - const block = - value instanceof Array - ? this._generateCalldataBlockFromArray(value, parentBlock) - : this._generateCalldataBlockFromObject(value, parentBlock); - return block; - } - - public generateValue(calldata: RawCalldata, rules: DecodingRules): any[] | object { - let members = this._members; - if (this._isArray && this._arrayLength === undefined) { - const arrayLengthBuf = calldata.popWord(); - const arrayLengthHex = ethUtil.bufferToHex(arrayLengthBuf); - const hexBase = 16; - const arrayLength = new BigNumber(arrayLengthHex, hexBase); - - [members] = this._createMembersWithLength(this.getDataItem(), arrayLength.toNumber()); - } - - calldata.startScope(); - let value: any[] | object; - if (rules.structsAsObjects && !this._isArray) { - value = {}; - _.each(this._memberMap, (idx: number, key: string) => { - const member = this._members[idx]; - const memberValue = member.generateValue(calldata, rules); - (value as { [key: string]: any })[key] = memberValue; - }); - } else { - value = []; - _.each(members, (member: DataType, idx: number) => { - const memberValue = member.generateValue(calldata, rules); - (value as any[]).push(memberValue); - }); - } - calldata.endScope(); - return value; - } - - public isStatic(): boolean { - /* For Tuple: - const isStaticTuple = this.children.length === 0; - return isStaticTuple; // @TODO: True in every case or only when dynamic data? - - For Array: - if isLengthDefined = false then this is false - - Otherwise if the first element is a Pointer then false - */ - - if (this._isArray && this._arrayLength === undefined) { - return false; - } - - // Search for dependent members - const dependentMember = _.find(this._members, (member: DataType) => { - return member instanceof DependentDataType; - }); - const isStatic = dependentMember === undefined; // static if we couldn't find a dependent member - return isStatic; - } - - protected _generateCalldataBlockFromArray(value: any[], parentBlock?: CalldataBlock): MemberCalldataBlock { - // Sanity check length - if (this._arrayLength !== undefined && value.length !== this._arrayLength) { - throw new Error( - `Expected array of ${JSON.stringify( - this._arrayLength, - )} elements, but got array of length ${JSON.stringify(value.length)}`, - ); - } - - const parentName = parentBlock === undefined ? '' : parentBlock.getName(); - const methodBlock: MemberCalldataBlock = new MemberCalldataBlock( - this.getDataItem().name, - this.getSignature(), - parentName, - ); - - let members = this._members; - if (this._isArray && this._arrayLength === undefined) { - [members] = this._createMembersWithLength(this.getDataItem(), value.length); - - const lenBuf = ethUtil.setLengthLeft( - ethUtil.toBuffer(`0x${value.length.toString(Constants.HEX_BASE)}`), - Constants.EVM_WORD_WIDTH_IN_BYTES, - ); - methodBlock.setHeader(lenBuf); - } - - const memberBlocks: CalldataBlock[] = []; - _.each(members, (member: DataType, idx: number) => { - const block = member.generateCalldataBlock(value[idx], methodBlock); - memberBlocks.push(block); - }); - methodBlock.setMembers(memberBlocks); - return methodBlock; - } - - protected _generateCalldataBlockFromObject(obj: object, parentBlock?: CalldataBlock): MemberCalldataBlock { - const parentName = parentBlock === undefined ? '' : parentBlock.getName(); - const methodBlock: MemberCalldataBlock = new MemberCalldataBlock( - this.getDataItem().name, - this.getSignature(), - parentName, - ); - const memberBlocks: CalldataBlock[] = []; - const childMap = _.cloneDeep(this._memberMap); - _.forOwn(obj, (value: any, key: string) => { - if (!(key in childMap)) { - throw new Error( - `Could not assign tuple to object: unrecognized key '${key}' in object ${this.getDataItem().name}`, - ); - } - const block = this._members[this._memberMap[key]].generateCalldataBlock(value, methodBlock); - memberBlocks.push(block); - delete childMap[key]; - }); - - if (Object.keys(childMap).length !== 0) { - throw new Error(`Could not assign tuple to object: missing keys ${Object.keys(childMap)}`); - } - - methodBlock.setMembers(memberBlocks); - return methodBlock; - } - - protected _computeSignatureOfMembers(): string { - // Compute signature of members - let signature = `(`; - _.each(this._members, (member: DataType, i: number) => { - signature += member.getSignature(); - if (i < this._members.length - 1) { - signature += ','; - } - }); - signature += ')'; - return signature; - } - - private _createMembersWithKeys(dataItem: DataItem): [DataType[], MemberMap] { - // Sanity check - if (dataItem.components === undefined) { - throw new Error(`Expected components`); - } - - const members: DataType[] = []; - const memberMap: MemberMap = {}; - _.each(dataItem.components, (memberItem: DataItem) => { - const childDataItem: DataItem = { - type: memberItem.type, - name: `${dataItem.name}.${memberItem.name}`, - }; - const components = memberItem.components; - if (components !== undefined) { - childDataItem.components = components; - } - const child = this.getFactory().create(childDataItem, this); - memberMap[memberItem.name] = members.length; - members.push(child); - }); - - return [members, memberMap]; - } - - private _createMembersWithLength(dataItem: DataItem, length: number): [DataType[], MemberMap] { - const members: DataType[] = []; - const memberMap: MemberMap = {}; - const range = _.range(length); - _.each(range, (idx: number) => { - const childDataItem: DataItem = { - type: this._arrayElementType ? this._arrayElementType : '', - name: `${dataItem.name}[${idx.toString(Constants.DEC_BASE)}]`, - }; - const components = dataItem.components; - if (components !== undefined) { - childDataItem.components = components; - } - const child = this.getFactory().create(childDataItem, this); - memberMap[idx.toString(Constants.DEC_BASE)] = members.length; - members.push(child); - }); - - return [members, memberMap]; - } -} diff --git a/packages/utils/src/abi_encoder/evm_data_type_factory.ts b/packages/utils/src/abi_encoder/evm_data_type_factory.ts index a3e1d404e..5d37acad9 100644 --- a/packages/utils/src/abi_encoder/evm_data_type_factory.ts +++ b/packages/utils/src/abi_encoder/evm_data_type_factory.ts @@ -3,7 +3,7 @@ /* tslint:disable no-construct */ import { DataItem, MethodAbi } from 'ethereum-types'; -import { DataType, DataTypeFactory } from './data_type'; +import { DataType, DataTypeFactory } from './abstract_data_types'; import * as Impl from './evm_data_types'; export class Address extends Impl.Address { 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 3e2c9e78c..707e265f8 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/address.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/address.ts @@ -3,9 +3,9 @@ import { DataItem } from 'ethereum-types'; import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; +import { DataTypeFactory, PayloadDataType } from '../abstract_data_types'; import { RawCalldata } from '../calldata'; import * as Constants from '../constants'; -import { DataTypeFactory, PayloadDataType } from '../data_type'; export class Address extends PayloadDataType { public static ERROR_MESSAGE_ADDRESS_MUST_START_WITH_0X = "Address must start with '0x'"; @@ -13,7 +13,7 @@ export class Address extends PayloadDataType { private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true; private static readonly _ADDRESS_SIZE_IN_BYTES = 20; private static readonly _DECODED_ADDRESS_OFFSET_IN_BYTES = Constants.EVM_WORD_WIDTH_IN_BYTES - - Address._ADDRESS_SIZE_IN_BYTES; + Address._ADDRESS_SIZE_IN_BYTES; public static matchType(type: string): boolean { return type === 'address'; 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 707af7c7e..f334282b8 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/array.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/array.ts @@ -1,7 +1,7 @@ import { DataItem } from 'ethereum-types'; +import { DataTypeFactory, MemberDataType } from '../abstract_data_types'; import * as Constants from '../constants'; -import { DataTypeFactory, MemberDataType } from '../data_type'; export class Array extends MemberDataType { private static readonly _matcher = RegExp('^(.+)\\[([0-9]*)\\]$'); 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 aee2727c7..4b9dd32b1 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/bool.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/bool.ts @@ -4,9 +4,9 @@ import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; import { BigNumber } from '../../configured_bignumber'; +import { DataTypeFactory, PayloadDataType } from '../abstract_data_types'; import { RawCalldata } from '../calldata'; import * as Constants from '../constants'; -import { DataTypeFactory, PayloadDataType } from '../data_type'; export class Bool extends PayloadDataType { private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true; 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 51165881a..5fca668e4 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 @@ -3,9 +3,9 @@ import { DataItem } from 'ethereum-types'; import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; +import { DataTypeFactory, PayloadDataType } from '../abstract_data_types'; import { RawCalldata } from '../calldata'; import * as Constants from '../constants'; -import { DataTypeFactory, PayloadDataType } from '../data_type'; export class DynamicBytes extends PayloadDataType { private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = false; 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 ba5b4cac9..ec41b9cfc 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/int.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/int.ts @@ -2,7 +2,7 @@ import { DataItem } from 'ethereum-types'; import { BigNumber } from '../../configured_bignumber'; -import { DataTypeFactory } from '../data_type'; +import { DataTypeFactory } from '../abstract_data_types'; import { Number } from './number'; 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 c4e6ee93a..ce33755f1 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/method.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/method.ts @@ -2,9 +2,9 @@ import { DataItem, MethodAbi } from 'ethereum-types'; import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; +import { DataType, DataTypeFactory, MemberDataType } from '../abstract_data_types'; import { RawCalldata } from '../calldata'; import * as Constants from '../constants'; -import { DataType, DataTypeFactory, MemberDataType } from '../data_type'; import { DecodingRules, EncodingRules } from '../utils/rules'; import { StaticBytes } from './static_bytes'; diff --git a/packages/utils/src/abi_encoder/evm_data_types/number.ts b/packages/utils/src/abi_encoder/evm_data_types/number.ts index 17201362e..8ff5e9a6a 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/number.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/number.ts @@ -3,9 +3,9 @@ import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; import { BigNumber } from '../../configured_bignumber'; +import { DataTypeFactory, PayloadDataType } from '../abstract_data_types'; import { RawCalldata } from '../calldata'; import * as Constants from '../constants'; -import { DataTypeFactory, PayloadDataType } from '../data_type'; export abstract class Number extends PayloadDataType { private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true; 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 e0bd3509c..d4411df9b 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/pointer.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/pointer.ts @@ -1,6 +1,6 @@ import { DataItem } from 'ethereum-types'; -import { DataType, DataTypeFactory, DependentDataType } from '../data_type'; +import { DataType, DataTypeFactory, DependentDataType } from '../abstract_data_types'; export class Pointer extends DependentDataType { constructor(destDataType: DataType, parentDataType: DataType, dataTypeFactory: DataTypeFactory) { 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 309dca234..90e872c78 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 @@ -2,9 +2,9 @@ import { DataItem } from 'ethereum-types'; import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; +import { DataTypeFactory, PayloadDataType } from '../abstract_data_types'; import { RawCalldata } from '../calldata'; import * as Constants from '../constants'; -import { DataTypeFactory, PayloadDataType } from '../data_type'; export class StaticBytes extends PayloadDataType { private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true; @@ -46,7 +46,7 @@ export class StaticBytes extends PayloadDataType { if (valueBuf.byteLength > this._width) { throw new Error( `Tried to assign ${value} (${ - valueBuf.byteLength + valueBuf.byteLength } bytes), which exceeds max bytes that can be stored in a ${this.getSignature()}`, ); } else if (value.length % 2 !== 0) { 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 96b36e735..c0bde8649 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/string.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/string.ts @@ -3,9 +3,9 @@ import { DataItem } from 'ethereum-types'; import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; +import { DataTypeFactory, PayloadDataType } from '../abstract_data_types'; import { RawCalldata } from '../calldata'; import * as Constants from '../constants'; -import { DataTypeFactory, PayloadDataType } from '../data_type'; export class String extends PayloadDataType { private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = false; 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 0db29c1eb..4a90e375a 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/tuple.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/tuple.ts @@ -1,6 +1,6 @@ import { DataItem } from 'ethereum-types'; -import { DataTypeFactory, MemberDataType } from '../data_type'; +import { DataTypeFactory, MemberDataType } from '../abstract_data_types'; export class Tuple extends MemberDataType { private readonly _tupleSignature: string; 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 86b31ab4c..ced3ef08b 100644 --- a/packages/utils/src/abi_encoder/evm_data_types/uint.ts +++ b/packages/utils/src/abi_encoder/evm_data_types/uint.ts @@ -2,7 +2,7 @@ import { DataItem } from 'ethereum-types'; import { BigNumber } from '../../configured_bignumber'; -import { DataTypeFactory } from '../data_type'; +import { DataTypeFactory } from '../abstract_data_types'; import { Number } from './number'; |