diff options
Diffstat (limited to 'packages/utils/src/abi_encoder/abstract_data_types')
5 files changed, 0 insertions, 413 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 deleted file mode 100644 index f23324721..000000000 --- a/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { DataItem } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { Calldata } from '../calldata/calldata'; -import { CalldataBlock } from '../calldata/calldata_block'; -import { RawCalldata } from '../calldata/raw_calldata'; -import { constants } from '../utils/constants'; -import { DecodingRules, EncodingRules } from '../utils/rules'; - -import { DataTypeFactory } from './interfaces'; - -export abstract class DataType { - 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_ = _.isUndefined(rules) ? constants.DEFAULT_ENCODING_RULES : rules; - const calldata = new Calldata(rules_); - if (!_.isUndefined(selector)) { - calldata.setSelector(selector); - } - const block = this.generateCalldataBlock(value); - calldata.setRoot(block); - const encodedCalldata = calldata.toString(); - return encodedCalldata; - } - - public decode(calldata: string, rules?: DecodingRules, selector?: string): any { - if (!_.isUndefined(selector) && !_.startsWith(calldata, selector)) { - throw new Error( - `Tried to decode calldata, but it was missing the function selector. Expected prefix '${selector}'. Got '${calldata}'.`, - ); - } - 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_); - return value; - } - - public decodeAsArray(returndata: string, rules?: DecodingRules): any[] { - const value = this.decode(returndata, rules); - const valuesAsArray = _.isObject(value) ? _.values(value) : [value]; - return valuesAsArray; - } - - public getSignature(isDetailed?: boolean): string { - if (_.isEmpty(this._dataItem.name) || !isDetailed) { - return this.getSignatureType(); - } - const name = this.getDataItem().name; - const lastIndexOfScopeDelimiter = name.lastIndexOf('.'); - const isScopedName = !_.isUndefined(lastIndexOfScopeDelimiter) && lastIndexOfScopeDelimiter > 0; - const shortName = isScopedName ? name.substr((lastIndexOfScopeDelimiter as number) + 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 getSignatureType(): string; - public abstract isStatic(): boolean; -} diff --git a/packages/utils/src/abi_encoder/abstract_data_types/interfaces.ts b/packages/utils/src/abi_encoder/abstract_data_types/interfaces.ts deleted file mode 100644 index 2f2f60871..000000000 --- a/packages/utils/src/abi_encoder/abstract_data_types/interfaces.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { DataItem } from 'ethereum-types'; - -import { RawCalldata } from '../calldata/raw_calldata'; - -import { DataType } from './data_type'; - -export interface DataTypeFactory { - create: (dataItem: DataItem, parentDataType?: DataType) => DataType; -} - -export interface DataTypeStaticInterface { - matchType: (type: string) => boolean; - encodeValue: (value: any) => Buffer; - decodeValue: (rawCalldata: RawCalldata) => any; -} - -export interface MemberIndexByName { - [key: string]: number; -} diff --git a/packages/utils/src/abi_encoder/abstract_data_types/types/blob.ts b/packages/utils/src/abi_encoder/abstract_data_types/types/blob.ts deleted file mode 100644 index a091e55b9..000000000 --- a/packages/utils/src/abi_encoder/abstract_data_types/types/blob.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { DataItem } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { BlobCalldataBlock } from '../../calldata/blocks/blob'; -import { CalldataBlock } from '../../calldata/calldata_block'; -import { RawCalldata } from '../../calldata/raw_calldata'; -import { DecodingRules } from '../../utils/rules'; - -import { DataType } from '../data_type'; -import { DataTypeFactory } from '../interfaces'; - -export abstract class AbstractBlobDataType extends DataType { - protected _sizeKnownAtCompileTime: boolean; - - public constructor(dataItem: DataItem, factory: DataTypeFactory, sizeKnownAtCompileTime: boolean) { - super(dataItem, factory); - this._sizeKnownAtCompileTime = sizeKnownAtCompileTime; - } - - public generateCalldataBlock(value: any, parentBlock?: CalldataBlock): BlobCalldataBlock { - const encodedValue = this.encodeValue(value); - const name = this.getDataItem().name; - const signature = this.getSignature(); - const parentName = _.isUndefined(parentBlock) ? '' : parentBlock.getName(); - const block = new BlobCalldataBlock(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._sizeKnownAtCompileTime; - } - - public abstract encodeValue(value: any): Buffer; - public abstract decodeValue(calldata: RawCalldata): any; -} diff --git a/packages/utils/src/abi_encoder/abstract_data_types/types/pointer.ts b/packages/utils/src/abi_encoder/abstract_data_types/types/pointer.ts deleted file mode 100644 index 0f3c55280..000000000 --- a/packages/utils/src/abi_encoder/abstract_data_types/types/pointer.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { DataItem } from 'ethereum-types'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { PointerCalldataBlock } from '../../calldata/blocks/pointer'; -import { CalldataBlock } from '../../calldata/calldata_block'; -import { RawCalldata } from '../../calldata/raw_calldata'; -import { constants } from '../../utils/constants'; -import { DecodingRules } from '../../utils/rules'; - -import { DataType } from '../data_type'; -import { DataTypeFactory } from '../interfaces'; - -export abstract class AbstractPointerDataType extends DataType { - protected _destination: DataType; - protected _parent: DataType; - - public constructor(dataItem: DataItem, factory: DataTypeFactory, destination: DataType, parent: DataType) { - super(dataItem, factory); - this._destination = destination; - this._parent = parent; - } - - public generateCalldataBlock(value: any, parentBlock?: CalldataBlock): PointerCalldataBlock { - if (_.isUndefined(parentBlock)) { - throw new Error(`DependentDataType requires a parent block to generate its block`); - } - const destinationBlock = this._destination.generateCalldataBlock(value, parentBlock); - const name = this.getDataItem().name; - const signature = this.getSignature(); - const parentName = parentBlock.getName(); - const block = new PointerCalldataBlock(name, signature, parentName, destinationBlock, parentBlock); - return block; - } - - public generateValue(calldata: RawCalldata, rules: DecodingRules): any { - const destinationOffsetBuf = calldata.popWord(); - const destinationOffsetHex = ethUtil.bufferToHex(destinationOffsetBuf); - const destinationOffsetRelative = parseInt(destinationOffsetHex, constants.HEX_BASE); - const destinationOffsetAbsolute = calldata.toAbsoluteOffset(destinationOffsetRelative); - const currentOffset = calldata.getOffset(); - calldata.setOffset(destinationOffsetAbsolute); - const value = this._destination.generateValue(calldata, rules); - calldata.setOffset(currentOffset); - return value; - } - - // Disable prefer-function-over-method for inherited abstract method. - /* tslint:disable prefer-function-over-method */ - public isStatic(): boolean { - return true; - } - /* tslint:enable prefer-function-over-method */ -} 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 deleted file mode 100644 index 2c6c4b0f6..000000000 --- a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts +++ /dev/null @@ -1,224 +0,0 @@ -import { ObjectMap } from '@0x/types'; -import { DataItem } from 'ethereum-types'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { BigNumber } from '../../../configured_bignumber'; -import { SetCalldataBlock } from '../../calldata/blocks/set'; -import { CalldataBlock } from '../../calldata/calldata_block'; -import { RawCalldata } from '../../calldata/raw_calldata'; -import { constants } from '../../utils/constants'; -import { DecodingRules } from '../../utils/rules'; - -import { DataType } from '../data_type'; -import { DataTypeFactory, MemberIndexByName } from '../interfaces'; - -import { AbstractPointerDataType } from './pointer'; - -export abstract class AbstractSetDataType extends DataType { - protected readonly _arrayLength: number | undefined; - protected readonly _arrayElementType: string | undefined; - private readonly _memberIndexByName: MemberIndexByName; - 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._memberIndexByName = {}; - this._members = []; - this._isArray = isArray; - this._arrayLength = arrayLength; - this._arrayElementType = arrayElementType; - if (isArray && !_.isUndefined(arrayLength)) { - [this._members, this._memberIndexByName] = this._createMembersWithLength(dataItem, arrayLength); - } else if (!isArray) { - [this._members, this._memberIndexByName] = this._createMembersWithKeys(dataItem); - } - } - - public generateCalldataBlock(value: any[] | object, parentBlock?: CalldataBlock): SetCalldataBlock { - 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; - // Case 1: This is an array of undefined length, which means that `this._members` was not - // populated in the constructor. So we must construct the set of members now. - if (this._isArray && _.isUndefined(this._arrayLength)) { - const arrayLengthBuf = calldata.popWord(); - const arrayLengthHex = ethUtil.bufferToHex(arrayLengthBuf); - const arrayLength = new BigNumber(arrayLengthHex, constants.HEX_BASE); - [members] = this._createMembersWithLength(this.getDataItem(), arrayLength.toNumber()); - } - // Create a new scope in the calldata, before descending into the members of this set. - calldata.startScope(); - let value: any[] | object; - if (rules.shouldConvertStructsToObjects && !this._isArray) { - // Construct an object with values for each member of the set. - value = {}; - _.each(this._memberIndexByName, (idx: number, key: string) => { - const member = this._members[idx]; - const memberValue = member.generateValue(calldata, rules); - (value as { [key: string]: any })[key] = memberValue; - }); - } else { - // Construct an array with values for each member of the set. - value = []; - _.each(members, (member: DataType, idx: number) => { - const memberValue = member.generateValue(calldata, rules); - (value as any[]).push(memberValue); - }); - } - // Close this scope and return tetheh value. - calldata.endScope(); - return value; - } - - public isStatic(): boolean { - // An array with an undefined length is never static. - if (this._isArray && _.isUndefined(this._arrayLength)) { - return false; - } - // If any member of the set is a pointer then the set is not static. - const dependentMember = _.find(this._members, (member: DataType) => { - return member instanceof AbstractPointerDataType; - }); - const isStatic = _.isUndefined(dependentMember); - return isStatic; - } - - 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) { - throw new Error( - `Expected array of ${JSON.stringify( - this._arrayLength, - )} elements, but got array of length ${JSON.stringify(value.length)}`, - ); - } - // Create a new calldata block for this set. - const parentName = _.isUndefined(parentBlock) ? '' : parentBlock.getName(); - const block = new SetCalldataBlock(this.getDataItem().name, this.getSignature(), parentName); - // If this set has an undefined length then set its header to be the number of elements. - let members = this._members; - if (this._isArray && _.isUndefined(this._arrayLength)) { - [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, - ); - block.setHeader(lenBuf); - } - // Create blocks for members of set. - const memberCalldataBlocks: CalldataBlock[] = []; - _.each(members, (member: DataType, idx: number) => { - const memberBlock = member.generateCalldataBlock(value[idx], block); - memberCalldataBlocks.push(memberBlock); - }); - block.setMembers(memberCalldataBlocks); - return block; - } - - protected _generateCalldataBlockFromObject(obj: object, parentBlock?: CalldataBlock): SetCalldataBlock { - // Create a new calldata block for this set. - const parentName = _.isUndefined(parentBlock) ? '' : parentBlock.getName(); - const block = new SetCalldataBlock(this.getDataItem().name, this.getSignature(), parentName); - // Create blocks for members of set. - const memberCalldataBlocks: CalldataBlock[] = []; - _.forEach(this._memberIndexByName, (memberIndex: number, memberName: string) => { - if (!(memberName in obj)) { - throw new Error( - `Could not assign tuple to object: missing key '${memberName}' in object ${JSON.stringify(obj)}`, - ); - } - const memberValue: any = (obj as ObjectMap<any>)[memberName]; - const memberBlock = this._members[memberIndex].generateCalldataBlock(memberValue, block); - memberCalldataBlocks.push(memberBlock); - }); - // Associate member blocks with Set block. - block.setMembers(memberCalldataBlocks); - return block; - } - - protected _computeSignatureOfMembers(isDetailed?: boolean): string { - // Compute signature of members - let signature = `(`; - _.each(this._members, (member: DataType, i: number) => { - signature += member.getSignature(isDetailed); - if (i < this._members.length - 1) { - signature += ','; - } - }); - signature += ')'; - return signature; - } - - private _createMembersWithKeys(dataItem: DataItem): [DataType[], MemberIndexByName] { - // Sanity check - if (_.isUndefined(dataItem.components)) { - throw new Error( - `Tried to create a set using key/value pairs, but no components were defined by the input DataItem '${ - dataItem.name - }'.`, - ); - } - // Create one member for each component of `dataItem` - const members: DataType[] = []; - const memberIndexByName: MemberIndexByName = {}; - const memberNames: string[] = []; - _.each(dataItem.components, (memberItem: DataItem) => { - // If a component with `name` already exists then - // rename to `name_nameIdx` to avoid naming conflicts. - let memberName = memberItem.name; - let nameIdx = 0; - while (_.includes(memberNames, memberName) || _.isEmpty(memberName)) { - nameIdx++; - memberName = `${memberItem.name}_${nameIdx}`; - } - memberNames.push(memberName); - const childDataItem: DataItem = { - type: memberItem.type, - name: `${dataItem.name}.${memberName}`, - }; - const components = memberItem.components; - if (!_.isUndefined(components)) { - childDataItem.components = components; - } - const child = this.getFactory().create(childDataItem, this); - memberIndexByName[memberName] = members.length; - members.push(child); - }); - return [members, memberIndexByName]; - } - - private _createMembersWithLength(dataItem: DataItem, length: number): [DataType[], MemberIndexByName] { - // Create `length` members, deriving the type from `dataItem` - const members: DataType[] = []; - const memberIndexByName: MemberIndexByName = {}; - const range = _.range(length); - _.each(range, (idx: number) => { - const memberDataItem: DataItem = { - type: _.isUndefined(this._arrayElementType) ? '' : this._arrayElementType, - name: `${dataItem.name}[${idx.toString(constants.DEC_BASE)}]`, - }; - const components = dataItem.components; - if (!_.isUndefined(components)) { - memberDataItem.components = components; - } - const memberType = this.getFactory().create(memberDataItem, this); - memberIndexByName[idx.toString(constants.DEC_BASE)] = members.length; - members.push(memberType); - }); - return [members, memberIndexByName]; - } -} |