Payload -> Blob, Dependent -> Pointer, Member -> Set

This commit is contained in:
Greg Hysen
2018-11-25 18:24:46 -08:00
parent bb4d02e413
commit 9a51af46ee
25 changed files with 130 additions and 132 deletions

View File

@@ -1,5 +1,4 @@
export * from './interfaces';
export * from './data_type';
export * from './dependent_data_type';
export * from './member_data_type';
export * from './payload_data_type';
import * as AbstractDataTypes from './types';
export { AbstractDataTypes };

View File

@@ -1,13 +1,13 @@
import { DataItem } from 'ethereum-types';
import * as _ from 'lodash';
import { CalldataBlock, PayloadCalldataBlock, RawCalldata } from '../calldata';
import { DecodingRules } from '../utils/rules';
import { CalldataBlock, CalldataBlocks, RawCalldata } from '../../calldata';
import { DecodingRules } from '../../utils/rules';
import { DataType } from './data_type';
import { DataTypeFactory } from './interfaces';
import { DataType } from '../data_type';
import { DataTypeFactory } from '../interfaces';
export abstract class PayloadDataType extends DataType {
export abstract class Blob extends DataType {
protected _hasConstantSize: boolean;
public constructor(dataItem: DataItem, factory: DataTypeFactory, hasConstantSize: boolean) {
@@ -15,12 +15,12 @@ export abstract class PayloadDataType extends DataType {
this._hasConstantSize = hasConstantSize;
}
public generateCalldataBlock(value: any, parentBlock?: CalldataBlock): PayloadCalldataBlock {
public generateCalldataBlock(value: any, parentBlock?: CalldataBlock): CalldataBlocks.Blob {
const encodedValue = this.encodeValue(value);
const name = this.getDataItem().name;
const signature = this.getSignature();
const parentName = parentBlock ? parentBlock.getName() : '';
const block = new PayloadCalldataBlock(name, signature, parentName, encodedValue);
const block = new CalldataBlocks.Blob(name, signature, parentName, encodedValue);
return block;
}

View File

@@ -0,0 +1,3 @@
export * from './blob';
export * from './pointer';
export * from './set';

View File

@@ -2,14 +2,14 @@ import { DataItem } from 'ethereum-types';
import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash';
import { CalldataBlock, DependentCalldataBlock, RawCalldata } from '../calldata';
import * as Constants from '../utils/constants';
import { DecodingRules } from '../utils/rules';
import { CalldataBlock, CalldataBlocks, RawCalldata } from '../../calldata';
import * as Constants from '../../utils/constants';
import { DecodingRules } from '../../utils/rules';
import { DataType } from './data_type';
import { DataTypeFactory } from './interfaces';
import { DataType } from '../data_type';
import { DataTypeFactory } from '../interfaces';
export abstract class DependentDataType extends DataType {
export abstract class Pointer extends DataType {
protected _dependency: DataType;
protected _parent: DataType;
private readonly _isStatic: boolean;
@@ -21,7 +21,7 @@ export abstract class DependentDataType extends DataType {
this._isStatic = true;
}
public generateCalldataBlock(value: any, parentBlock?: CalldataBlock): DependentCalldataBlock {
public generateCalldataBlock(value: any, parentBlock?: CalldataBlock): CalldataBlocks.Pointer {
if (parentBlock === undefined) {
throw new Error(`DependentDataType requires a parent block to generate its block`);
}
@@ -29,7 +29,7 @@ export abstract class DependentDataType extends DataType {
const name = this.getDataItem().name;
const signature = this.getSignature();
const parentName = parentBlock ? parentBlock.getName() : '';
const block = new DependentCalldataBlock(name, signature, parentName, dependencyBlock, parentBlock);
const block = new CalldataBlocks.Pointer(name, signature, parentName, dependencyBlock, parentBlock);
return block;
}

View File

@@ -2,16 +2,17 @@ import { DataItem } from 'ethereum-types';
import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash';
import { BigNumber } from '../../configured_bignumber';
import { CalldataBlock, MemberCalldataBlock, RawCalldata } from '../calldata';
import * as Constants from '../utils/constants';
import { DecodingRules } from '../utils/rules';
import { BigNumber } from '../../../configured_bignumber';
import { CalldataBlock, CalldataBlocks, RawCalldata } from '../../calldata';
import * as Constants from '../../utils/constants';
import { DecodingRules } from '../../utils/rules';
import { DataType } from './data_type';
import { DependentDataType } from './dependent_data_type';
import { DataTypeFactory, MemberIndexByName } from './interfaces';
import { DataType } from '../data_type';
import { DataTypeFactory, MemberIndexByName } from '../interfaces';
export abstract class MemberDataType extends DataType {
import { Pointer } from './pointer';
export abstract class Set extends DataType {
protected readonly _arrayLength: number | undefined;
protected readonly _arrayElementType: string | undefined;
private readonly _memberIndexByName: MemberIndexByName;
@@ -38,7 +39,7 @@ export abstract class MemberDataType extends DataType {
}
}
public generateCalldataBlock(value: any[] | object, parentBlock?: CalldataBlock): MemberCalldataBlock {
public generateCalldataBlock(value: any[] | object, parentBlock?: CalldataBlock): CalldataBlocks.Set {
const block =
value instanceof Array
? this._generateCalldataBlockFromArray(value, parentBlock)
@@ -94,13 +95,13 @@ export abstract class MemberDataType extends DataType {
// Search for dependent members
const dependentMember = _.find(this._members, (member: DataType) => {
return member instanceof DependentDataType;
return member instanceof Pointer;
});
const isStatic = dependentMember === undefined; // static if we couldn't find a dependent member
return isStatic;
}
protected _generateCalldataBlockFromArray(value: any[], parentBlock?: CalldataBlock): MemberCalldataBlock {
protected _generateCalldataBlockFromArray(value: any[], parentBlock?: CalldataBlock): CalldataBlocks.Set {
// Sanity check length
if (this._arrayLength !== undefined && value.length !== this._arrayLength) {
throw new Error(
@@ -111,7 +112,7 @@ export abstract class MemberDataType extends DataType {
}
const parentName = parentBlock === undefined ? '' : parentBlock.getName();
const methodBlock: MemberCalldataBlock = new MemberCalldataBlock(
const methodBlock: CalldataBlocks.Set = new CalldataBlocks.Set(
this.getDataItem().name,
this.getSignature(),
parentName,
@@ -128,23 +129,23 @@ export abstract class MemberDataType extends DataType {
methodBlock.setHeader(lenBuf);
}
const memberBlocks: CalldataBlock[] = [];
const memberCalldataBlocks: CalldataBlock[] = [];
_.each(members, (member: DataType, idx: number) => {
const block = member.generateCalldataBlock(value[idx], methodBlock);
memberBlocks.push(block);
memberCalldataBlocks.push(block);
});
methodBlock.setMembers(memberBlocks);
methodBlock.setMembers(memberCalldataBlocks);
return methodBlock;
}
protected _generateCalldataBlockFromObject(obj: object, parentBlock?: CalldataBlock): MemberCalldataBlock {
protected _generateCalldataBlockFromObject(obj: object, parentBlock?: CalldataBlock): CalldataBlocks.Set {
const parentName = parentBlock === undefined ? '' : parentBlock.getName();
const methodBlock: MemberCalldataBlock = new MemberCalldataBlock(
const methodBlock: CalldataBlocks.Set = new CalldataBlocks.Set(
this.getDataItem().name,
this.getSignature(),
parentName,
);
const memberBlocks: CalldataBlock[] = [];
const memberCalldataBlocks: CalldataBlock[] = [];
const childMap = _.cloneDeep(this._memberIndexByName);
_.forOwn(obj, (value: any, key: string) => {
if (!(key in childMap)) {
@@ -153,7 +154,7 @@ export abstract class MemberDataType extends DataType {
);
}
const block = this._members[this._memberIndexByName[key]].generateCalldataBlock(value, methodBlock);
memberBlocks.push(block);
memberCalldataBlocks.push(block);
delete childMap[key];
});
@@ -161,7 +162,7 @@ export abstract class MemberDataType extends DataType {
throw new Error(`Could not assign tuple to object: missing keys ${Object.keys(childMap)}`);
}
methodBlock.setMembers(memberBlocks);
methodBlock.setMembers(memberCalldataBlocks);
return methodBlock;
}

View File

@@ -0,0 +1,20 @@
import { CalldataBlock } from '../calldata_block';
export class Blob extends CalldataBlock {
private readonly _blob: Buffer;
constructor(name: string, signature: string, parentName: string, blob: Buffer) {
const headerSizeInBytes = 0;
const bodySizeInBytes = blob.byteLength;
super(name, signature, parentName, headerSizeInBytes, bodySizeInBytes);
this._blob = blob;
}
public toBuffer(): Buffer {
return this._blob;
}
public getRawData(): Buffer {
return this._blob;
}
}

View File

@@ -0,0 +1,3 @@
export * from './blob';
export * from './pointer';
export * from './set';

View File

@@ -1,10 +1,10 @@
import * as ethUtil from 'ethereumjs-util';
import * as Constants from '../utils/constants';
import * as Constants from '../../utils/constants';
import { CalldataBlock } from './calldata_block';
import { CalldataBlock } from '../calldata_block';
export class DependentCalldataBlock extends CalldataBlock {
export class Pointer extends CalldataBlock {
public static readonly RAW_DATA_START = new Buffer('<');
public static readonly RAW_DATA_END = new Buffer('>');
private static readonly _DEPENDENT_PAYLOAD_SIZE_IN_BYTES = 32;
@@ -14,8 +14,8 @@ export class DependentCalldataBlock extends CalldataBlock {
private _aliasFor: CalldataBlock | undefined;
constructor(name: string, signature: string, parentName: string, dependency: CalldataBlock, parent: CalldataBlock) {
const headerSizeInBytes = DependentCalldataBlock._EMPTY_HEADER_SIZE;
const bodySizeInBytes = DependentCalldataBlock._DEPENDENT_PAYLOAD_SIZE_IN_BYTES;
const headerSizeInBytes = Pointer._EMPTY_HEADER_SIZE;
const bodySizeInBytes = Pointer._DEPENDENT_PAYLOAD_SIZE_IN_BYTES;
super(name, signature, parentName, headerSizeInBytes, bodySizeInBytes);
this._parent = parent;
this._dependency = dependency;
@@ -28,9 +28,9 @@ export class DependentCalldataBlock extends CalldataBlock {
const parentOffset = this._parent.getOffsetInBytes();
const parentHeaderSize = this._parent.getHeaderSizeInBytes();
const pointer: number = destinationOffset - (parentOffset + parentHeaderSize);
const pointerBuf = ethUtil.toBuffer(`0x${pointer.toString(Constants.HEX_BASE)}`);
const evmWordWidthInBytes = 32;
const pointerBufPadded = ethUtil.setLengthLeft(pointerBuf, evmWordWidthInBytes);
const pointerHex = `0x${pointer.toString(Constants.HEX_BASE)}`;
const pointerBuf = ethUtil.toBuffer(pointerHex);
const pointerBufPadded = ethUtil.setLengthLeft(pointerBuf, Constants.EVM_WORD_WIDTH_IN_BYTES);
return pointerBufPadded;
}
@@ -50,9 +50,9 @@ export class DependentCalldataBlock extends CalldataBlock {
public getRawData(): Buffer {
const dependencyRawData = this._dependency.getRawData();
const rawDataComponents: Buffer[] = [];
rawDataComponents.push(DependentCalldataBlock.RAW_DATA_START);
rawDataComponents.push(Pointer.RAW_DATA_START);
rawDataComponents.push(dependencyRawData);
rawDataComponents.push(DependentCalldataBlock.RAW_DATA_END);
rawDataComponents.push(Pointer.RAW_DATA_END);
const rawData = Buffer.concat(rawDataComponents);
return rawData;
}

View File

@@ -1,8 +1,8 @@
import * as _ from 'lodash';
import { CalldataBlock } from './calldata_block';
import { CalldataBlock } from '../calldata_block';
export class MemberCalldataBlock extends CalldataBlock {
export class Set extends CalldataBlock {
private _header: Buffer | undefined;
private _members: CalldataBlock[];
@@ -14,14 +14,13 @@ export class MemberCalldataBlock extends CalldataBlock {
public getRawData(): Buffer {
const rawDataComponents: Buffer[] = [];
if (this._header !== undefined) {
if (this._header) {
rawDataComponents.push(this._header);
}
_.each(this._members, (member: CalldataBlock) => {
const memberBuffer = member.getRawData();
rawDataComponents.push(memberBuffer);
});
const rawData = Buffer.concat(rawDataComponents);
return rawData;
}
@@ -36,7 +35,7 @@ export class MemberCalldataBlock extends CalldataBlock {
}
public toBuffer(): Buffer {
if (this._header !== undefined) {
if (this._header) {
return this._header;
}
return new Buffer('');

View File

@@ -5,8 +5,8 @@ import * as Constants from '../utils/constants';
import { Queue } from '../utils/queue';
import { EncodingRules } from '../utils/rules';
import * as CalldataBlocks from './blocks';
import { CalldataBlock } from './calldata_block';
import * as CalldataBlocks from './calldata_blocks';
export class Calldata {
private readonly _rules: EncodingRules;
@@ -18,7 +18,7 @@ export class Calldata {
const blockQueue = new Queue<CalldataBlock>();
// Base Case
if (!(block instanceof CalldataBlocks.MemberCalldataBlock)) {
if (!(block instanceof CalldataBlocks.Set)) {
blockQueue.pushBack(block);
return blockQueue;
}
@@ -26,7 +26,7 @@ export class Calldata {
// This is a Member Block
const memberBlock = block;
_.eachRight(memberBlock.getMembers(), (member: CalldataBlock) => {
if (member instanceof CalldataBlocks.MemberCalldataBlock) {
if (member instanceof CalldataBlocks.Set) {
blockQueue.mergeFront(Calldata._createQueue(member));
} else {
blockQueue.pushFront(member);
@@ -35,9 +35,9 @@ export class Calldata {
// Children
_.each(memberBlock.getMembers(), (member: CalldataBlock) => {
if (member instanceof CalldataBlocks.DependentCalldataBlock && member.getAlias() === undefined) {
if (member instanceof CalldataBlocks.Pointer && member.getAlias() === undefined) {
const dependency = member.getDependency();
if (dependency instanceof CalldataBlocks.MemberCalldataBlock) {
if (dependency instanceof CalldataBlocks.Set) {
blockQueue.mergeBack(Calldata._createQueue(dependency));
} else {
blockQueue.pushBack(dependency);
@@ -68,7 +68,7 @@ export class Calldata {
const subtreeQueue = Calldata._createQueue(this._root);
let block: CalldataBlock | undefined;
for (block = subtreeQueue.popBack(); block !== undefined; block = subtreeQueue.popBack()) {
if (block instanceof CalldataBlocks.DependentCalldataBlock) {
if (block instanceof CalldataBlocks.Pointer) {
const dependencyBlockHashBuf = block.getDependency().computeHash();
const dependencyBlockHash = ethUtil.bufferToHex(dependencyBlockHashBuf);
if (dependencyBlockHash in blocksByHash) {
@@ -175,7 +175,7 @@ export class Calldata {
),
)
.padEnd(valuePadding);
if (block instanceof CalldataBlocks.MemberCalldataBlock) {
if (block instanceof CalldataBlocks.Set) {
nameStr = `### ${prettyName.padEnd(namePadding)}`;
line = `\n${offsetStr}${value}${nameStr}`;
} else {

View File

@@ -1,3 +0,0 @@
export * from './dependent_calldata_block';
export * from './member_calldata_block';
export * from './payload_calldata_block';

View File

@@ -1,6 +1,5 @@
export * from './calldata_block';
export * from './dependent_calldata_block';
export * from './payload_calldata_block';
export * from './member_calldata_block';
export * from './calldata';
export * from './calldata_block';
export * from './raw_calldata';
import * as CalldataBlocks from './blocks';
export { CalldataBlocks };

View File

@@ -1,20 +0,0 @@
import { CalldataBlock } from './calldata_block';
export class PayloadCalldataBlock extends CalldataBlock {
private readonly _payload: Buffer;
constructor(name: string, signature: string, parentName: string, payload: Buffer) {
const headerSizeInBytes = 0;
const bodySizeInBytes = payload.byteLength;
super(name, signature, parentName, headerSizeInBytes, bodySizeInBytes);
this._payload = payload;
}
public toBuffer(): Buffer {
return this._payload;
}
public getRawData(): Buffer {
return this._payload;
}
}

View File

@@ -8,26 +8,25 @@ export class RawCalldata {
private readonly _value: Buffer;
private readonly _selector: string;
private readonly _scopes: Queue<number>;
private _offset: number; // tracks current offset into raw calldata; used for parsing
private _offset: number;
constructor(value: string | Buffer, hasSelectorPrefix: boolean = true) {
public constructor(value: string | Buffer, hasSelector: boolean = true) {
// Sanity check
if (typeof value === 'string' && !value.startsWith('0x')) {
throw new Error(`Expected raw calldata to start with '0x'`);
}
const valueBuf = ethUtil.toBuffer(value);
if (hasSelectorPrefix) {
this._selector = ethUtil.bufferToHex(
valueBuf.slice(Constants.HEX_SELECTOR_BYTE_OFFSET_IN_CALLDATA, Constants.HEX_SELECTOR_LENGTH_IN_BYTES),
);
this._value = valueBuf.slice(Constants.HEX_SELECTOR_LENGTH_IN_BYTES); // disregard selector
} else {
this._selector = '0x';
this._value = valueBuf;
}
// Construct initial values
this._value = ethUtil.toBuffer(value);
this._selector = '0x';
this._scopes = new Queue<number>();
this._scopes.pushBack(RawCalldata._INITIAL_OFFSET);
this._offset = RawCalldata._INITIAL_OFFSET;
// If there's a selector then slice it
if (hasSelector) {
const selectorBuf = this._value.slice(Constants.HEX_SELECTOR_LENGTH_IN_BYTES);
this._value = this._value.slice(Constants.HEX_SELECTOR_LENGTH_IN_BYTES);
this._selector = ethUtil.bufferToHex(selectorBuf);
}
}
public popBytes(lengthInBytes: number): Buffer {

View File

@@ -3,11 +3,11 @@ import { DataItem } from 'ethereum-types';
import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash';
import { DataTypeFactory, PayloadDataType } from '../abstract_data_types';
import { AbstractDataTypes, DataTypeFactory } from '../abstract_data_types';
import { RawCalldata } from '../calldata';
import * as Constants from '../utils/constants';
export class Address extends PayloadDataType {
export class Address extends AbstractDataTypes.Blob {
public static ERROR_MESSAGE_ADDRESS_MUST_START_WITH_0X = "Address must start with '0x'";
public static ERROR_MESSAGE_ADDRESS_MUST_BE_20_BYTES = 'Address must be 20 bytes';
private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true;

View File

@@ -1,9 +1,9 @@
import { DataItem } from 'ethereum-types';
import { DataTypeFactory, MemberDataType } from '../abstract_data_types';
import { AbstractDataTypes, DataTypeFactory } from '../abstract_data_types';
import * as Constants from '../utils/constants';
export class Array extends MemberDataType {
export class Array extends AbstractDataTypes.Set {
private static readonly _MATCHER = RegExp('^(.+)\\[([0-9]*)\\]$');
private readonly _arraySignature: string;
private readonly _elementType: string;

View File

@@ -4,11 +4,11 @@ import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash';
import { BigNumber } from '../../configured_bignumber';
import { DataTypeFactory, PayloadDataType } from '../abstract_data_types';
import { AbstractDataTypes, DataTypeFactory } from '../abstract_data_types';
import { RawCalldata } from '../calldata';
import * as Constants from '../utils/constants';
export class Bool extends PayloadDataType {
export class Bool extends AbstractDataTypes.Blob {
private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true;
public static matchType(type: string): boolean {

View File

@@ -3,11 +3,11 @@ import { DataItem } from 'ethereum-types';
import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash';
import { DataTypeFactory, PayloadDataType } from '../abstract_data_types';
import { AbstractDataTypes, DataTypeFactory } from '../abstract_data_types';
import { RawCalldata } from '../calldata';
import * as Constants from '../utils/constants';
export class DynamicBytes extends PayloadDataType {
export class DynamicBytes extends AbstractDataTypes.Blob {
private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = false;
public static matchType(type: string): boolean {

View File

@@ -2,21 +2,21 @@
import { DataItem } from 'ethereum-types';
import { BigNumber } from '../../configured_bignumber';
import { DataTypeFactory, PayloadDataType } from '../abstract_data_types';
import { AbstractDataTypes, DataTypeFactory } from '../abstract_data_types';
import { RawCalldata } from '../calldata';
import * as Constants from '../utils/constants';
import * as EncoderMath from '../utils/math';
export class Int extends PayloadDataType {
export class Int extends AbstractDataTypes.Blob {
private static readonly _MATCHER = RegExp(
'^int(8|16|24|32|40|48|56|64|72|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224|232|240|248|256){0,1}$',
);
private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true;
private static readonly _MAX_WIDTH: number = 256;
private static readonly _DEFAULT_WIDTH: number = Int._MAX_WIDTH;
private _width: number;
private _minValue: BigNumber;
private _maxValue: BigNumber;
private readonly _width: number;
private readonly _minValue: BigNumber;
private readonly _maxValue: BigNumber;
public static matchType(type: string): boolean {
return Int._MATCHER.test(type);

View File

@@ -2,13 +2,13 @@ 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 { AbstractDataTypes, DataType, DataTypeFactory } from '../abstract_data_types';
import * as Constants from '../utils/constants';
import { DecodingRules, EncodingRules } from '../utils/rules';
import { Tuple } from './tuple';
export class Method extends MemberDataType {
export class Method extends AbstractDataTypes.Set {
private readonly _methodSignature: string;
private readonly _methodSelector: string;
private readonly _returnDataType: DataType;

View File

@@ -1,8 +1,8 @@
import { DataItem } from 'ethereum-types';
import { DataType, DataTypeFactory, DependentDataType } from '../abstract_data_types';
import { AbstractDataTypes, DataType, DataTypeFactory } from '../abstract_data_types';
export class Pointer extends DependentDataType {
export class Pointer extends AbstractDataTypes.Pointer {
constructor(destDataType: DataType, parentDataType: DataType, dataTypeFactory: DataTypeFactory) {
const destDataItem = destDataType.getDataItem();
const dataItem: DataItem = { name: `ptr<${destDataItem.name}>`, type: `ptr<${destDataItem.type}>` };

View File

@@ -2,11 +2,11 @@ import { DataItem } from 'ethereum-types';
import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash';
import { DataTypeFactory, PayloadDataType } from '../abstract_data_types';
import { AbstractDataTypes, DataTypeFactory } from '../abstract_data_types';
import { RawCalldata } from '../calldata';
import * as Constants from '../utils/constants';
export class StaticBytes extends PayloadDataType {
export class StaticBytes extends AbstractDataTypes.Blob {
private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true;
private static readonly _MATCHER = RegExp(
'^(byte|bytes(1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32))$',

View File

@@ -3,11 +3,11 @@ import { DataItem } from 'ethereum-types';
import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash';
import { DataTypeFactory, PayloadDataType } from '../abstract_data_types';
import { AbstractDataTypes, DataTypeFactory } from '../abstract_data_types';
import { RawCalldata } from '../calldata';
import * as Constants from '../utils/constants';
export class String extends PayloadDataType {
export class String extends AbstractDataTypes.Blob {
private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = false;
public static matchType(type: string): boolean {

View File

@@ -1,8 +1,8 @@
import { DataItem } from 'ethereum-types';
import { DataTypeFactory, MemberDataType } from '../abstract_data_types';
import { AbstractDataTypes, DataTypeFactory } from '../abstract_data_types';
export class Tuple extends MemberDataType {
export class Tuple extends AbstractDataTypes.Set {
private readonly _signature: string;
public static matchType(type: string): boolean {

View File

@@ -2,21 +2,21 @@
import { DataItem } from 'ethereum-types';
import { BigNumber } from '../../configured_bignumber';
import { DataTypeFactory, PayloadDataType } from '../abstract_data_types';
import { AbstractDataTypes, DataTypeFactory } from '../abstract_data_types';
import { RawCalldata } from '../calldata';
import * as Constants from '../utils/constants';
import * as EncoderMath from '../utils/math';
export class UInt extends PayloadDataType {
export class UInt extends AbstractDataTypes.Blob {
private static readonly _MATCHER = RegExp(
'^uint(8|16|24|32|40|48|56|64|72|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224|232|240|248|256){0,1}$',
);
private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true;
private static readonly _MAX_WIDTH: number = 256;
private static readonly _DEFAULT_WIDTH: number = UInt._MAX_WIDTH;
private _width: number;
private _minValue: BigNumber;
private _maxValue: BigNumber;
private static readonly _MIN_VALUE = new BigNumber(0);
private readonly _width: number;
private readonly _maxValue: BigNumber;
public static matchType(type: string): boolean {
return UInt._MATCHER.test(type);
@@ -36,18 +36,17 @@ export class UInt extends PayloadDataType {
throw new Error(`Tried to instantiate UInt with bad input: ${dataItem}`);
}
this._width = UInt._decodeWidthFromType(dataItem.type);
this._minValue = new BigNumber(0);
this._maxValue = new BigNumber(2).toPower(this._width).sub(1);
}
public encodeValue(value: BigNumber | string | number): Buffer {
const encodedValue = EncoderMath.safeEncodeNumericValue(value, this._minValue, this._maxValue);
const encodedValue = EncoderMath.safeEncodeNumericValue(value, UInt._MIN_VALUE, this._maxValue);
return encodedValue;
}
public decodeValue(calldata: RawCalldata): BigNumber {
const valueBuf = calldata.popWord();
const value = EncoderMath.safeDecodeNumericValue(valueBuf, this._minValue, this._maxValue);
const value = EncoderMath.safeDecodeNumericValue(valueBuf, UInt._MIN_VALUE, this._maxValue);
return value;
}
@@ -55,4 +54,3 @@ export class UInt extends PayloadDataType {
return `uint${this._width}`;
}
}