From 52474a0b8edb2f49f850069c1a79dcd9b5d77e9d Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Mon, 12 Nov 2018 17:49:52 -0800 Subject: decoding with objects as structs works --- packages/order-utils/test/abi/data_type.ts | 37 ++++++++++++++++--------- packages/order-utils/test/abi/evm_data_types.ts | 21 ++++---------- packages/order-utils/test/abi_encoder_test.ts | 21 ++++++++++---- 3 files changed, 45 insertions(+), 34 deletions(-) diff --git a/packages/order-utils/test/abi/data_type.ts b/packages/order-utils/test/abi/data_type.ts index af170f7e6..725d314f3 100644 --- a/packages/order-utils/test/abi/data_type.ts +++ b/packages/order-utils/test/abi/data_type.ts @@ -4,7 +4,9 @@ import { BigNumber } from '@0x/utils'; import ethUtil = require('ethereumjs-util'); var _ = require('lodash'); - +export interface GenerateValueRules { + structsAsObjects: boolean; +} export abstract class DataType { private dataItem: DataItem; @@ -18,7 +20,7 @@ export abstract class DataType { } public abstract generateCalldataBlock(value: any, parentBlock?: CalldataBlock): CalldataBlock; - public abstract generateValue(calldata: RawCalldata): any; + public abstract generateValue(calldata: RawCalldata, rules: GenerateValueRules): any; public abstract encode(value: any, calldata: Calldata): void; public abstract getSignature(): string; public abstract isStatic(): boolean; @@ -47,7 +49,7 @@ export abstract class PayloadDataType extends DataType { // calldata.setRoot(block); } - public generateValue(calldata: RawCalldata): any { + public generateValue(calldata: RawCalldata, rules: GenerateValueRules): any { const value = this.decodeValue(calldata); return value; } @@ -88,13 +90,13 @@ export abstract class DependentDataType extends DataType { //calldata.setRoot(block); } - public generateValue(calldata: RawCalldata): any { + public generateValue(calldata: RawCalldata, rules: GenerateValueRules): any { const destinationOffsetBuf = calldata.popWord(); const currentOffset = calldata.getOffset(); const destinationOffsetRelative = parseInt(ethUtil.bufferToHex(destinationOffsetBuf), 16); const destinationOffsetAbsolute = calldata.toAbsoluteOffset(destinationOffsetRelative); calldata.setOffset(destinationOffsetAbsolute); - const value = this.dependency.generateValue(calldata); + const value = this.dependency.generateValue(calldata, rules); calldata.setOffset(currentOffset); return value; } @@ -237,7 +239,7 @@ export abstract class MemberDataType extends DataType { calldata.setRoot(block); } - public generateValue(calldata: RawCalldata): any[] { + public generateValue(calldata: RawCalldata, rules: GenerateValueRules): any[] | object { let members = this.members; if (this.isArray && this.arrayLength === undefined) { const arrayLengthBuf = calldata.popWord(); @@ -249,14 +251,23 @@ export abstract class MemberDataType extends DataType { } calldata.startScope(); - const decodedValue: any[] = []; - _.each(members, (member: DataType, idx: number) => { - let memberValue = member.generateValue(calldata); - decodedValue.push(memberValue); - }); + let value: any[] | object; + if (rules.structsAsObjects && !this.isArray) { + value = {}; + _.each(this.memberMap, (idx: number, key: string) => { + const member = this.members[idx]; + let memberValue = member.generateValue(calldata, rules); + (value as { [key: string]: any })[key] = memberValue; + }); + } else { + value = []; + _.each(members, (member: DataType, idx: number) => { + let memberValue = member.generateValue(calldata, rules); + (value as any[]).push(memberValue); + }); + } calldata.endScope(); - - return decodedValue; + return value; } protected computeSignatureOfMembers(): string { diff --git a/packages/order-utils/test/abi/evm_data_types.ts b/packages/order-utils/test/abi/evm_data_types.ts index abb4fba14..7b366a985 100644 --- a/packages/order-utils/test/abi/evm_data_types.ts +++ b/packages/order-utils/test/abi/evm_data_types.ts @@ -1,4 +1,4 @@ -import { DataType, DataTypeFactory, DataTypeFactoryImpl, PayloadDataType, DependentDataType, MemberDataType } from './data_type'; +import { GenerateValueRules, DataType, DataTypeFactory, DataTypeFactoryImpl, PayloadDataType, DependentDataType, MemberDataType } from './data_type'; import { MethodAbi, DataItem } from 'ethereum-types'; @@ -495,24 +495,15 @@ export class Method extends MemberDataType { return calldata.toHexString(); } - /* - protected decodeValue(value: Buffer): any[] { - const selectorBuf = value.slice(4); - const selectorHex = ethUtil.bufferToHex(selectorBuf); - if (this.selector !== selectorHex) { - throw new Error(`Tried to decode calldata with mismatched selector. Expected '${this.selector}', got '${selectorHex}'`); - } - const remainingValue = value.slice(9); - const decodedValue = super.decodeValue(remainingValue); - return decodedValue; - }*/ - - public decode(calldata: string): any[] { + public decode(calldata: string, decodeStructsAsObjects: boolean = false): any[] | object { const calldata_ = new RawCalldata(calldata); if (this.selector !== calldata_.getSelector()) { throw new Error(`Tried to decode calldata with mismatched selector. Expected '${this.selector}', got '${calldata_.getSelector()}'`); } - const value = super.generateValue(calldata_); + let rules: GenerateValueRules = { + structsAsObjects: decodeStructsAsObjects + }; + const value = super.generateValue(calldata_, rules); return value; } diff --git a/packages/order-utils/test/abi_encoder_test.ts b/packages/order-utils/test/abi_encoder_test.ts index 631255e68..137850b35 100644 --- a/packages/order-utils/test/abi_encoder_test.ts +++ b/packages/order-utils/test/abi_encoder_test.ts @@ -26,7 +26,7 @@ const expect = chai.expect; describe.only('ABI Encoder', () => { describe.only('ABI Tests at Method Level', () => { - it('Crazy ABI', async () => { + it.only('Crazy ABI', async () => { const method = new AbiEncoder.Method(AbiSamples.crazyAbi); console.log(method.getSignature()); @@ -78,7 +78,15 @@ describe.only('ABI Encoder', () => { }; const someArrayOfTuplesWithDynamicTypes = [someTupleWithDynamicTypes2, someTupleWithDynamicTypes3]; - const args = [someStaticArray, someStaticArrayWithDynamicMembers, someDynamicArrayWithDynamicMembers, some2DArray, someTuple, someTupleWithDynamicTypes, someArrayOfTuplesWithDynamicTypes]; + const args = { + someStaticArray: someStaticArray, + someStaticArrayWithDynamicMembers: someStaticArrayWithDynamicMembers, + someDynamicArrayWithDynamicMembers: someDynamicArrayWithDynamicMembers, + some2DArray: some2DArray, + someTuple: someTuple, + someTupleWithDynamicTypes: someTupleWithDynamicTypes, + someArrayOfTuplesWithDynamicTypes: someArrayOfTuplesWithDynamicTypes + }; const calldata = method.encode(args); console.log(calldata); @@ -91,13 +99,14 @@ describe.only('ABI Encoder', () => { expect(calldata).to.be.equal(expectedCalldata); // Test decoding - /*const expectedDecodedValueJson = JSON.stringify(args); - const decodedValue = method.decode(calldata); + const expectedDecodedValueJson = JSON.stringify(args); + const decodedValue = method.decode(calldata, true); const decodedValueJson = JSON.stringify(decodedValue); - expect(decodedValueJson).to.be.equal(expectedDecodedValueJson);*/ + console.log(`DECODED`, '*'.repeat(200), '\n', decodedValueJson); + expect(decodedValueJson).to.be.equal(expectedDecodedValueJson); }); - it.only('Crazy ABI #1', async () => { + it('Crazy ABI #1', async () => { const method = new AbiEncoder.Method(AbiSamples.crazyAbi1); const args = [ -- cgit