aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/utils/src/abi_encoder/calldata.ts12
-rw-r--r--packages/utils/src/abi_encoder/data_type.ts2
-rw-r--r--packages/utils/src/abi_encoder/evm_data_types.ts32
-rw-r--r--packages/utils/test/abi_encoder_test.ts29
-rw-r--r--packages/utils/test/abi_samples.ts34
5 files changed, 102 insertions, 7 deletions
diff --git a/packages/utils/src/abi_encoder/calldata.ts b/packages/utils/src/abi_encoder/calldata.ts
index 32278e5c5..078767c22 100644
--- a/packages/utils/src/abi_encoder/calldata.ts
+++ b/packages/utils/src/abi_encoder/calldata.ts
@@ -456,13 +456,19 @@ export class RawCalldata {
private selector: string;
private scopes: Queue<number>;
- constructor(value: string | Buffer) {
+ constructor(value: string | Buffer, hasSelectorPrefix: boolean = true) {
if (typeof value === 'string' && !value.startsWith('0x')) {
throw new Error(`Expected raw calldata to start with '0x'`);
}
const valueBuf = ethUtil.toBuffer(value);
- this.selector = ethUtil.bufferToHex(valueBuf.slice(0, 4));
- this.value = valueBuf.slice(4); // disregard selector
+ if (hasSelectorPrefix) {
+ this.selector = ethUtil.bufferToHex(valueBuf.slice(0, 4));
+ this.value = valueBuf.slice(4); // disregard selector
+ } else {
+ this.selector = '0x';
+ this.value = valueBuf;
+ }
+
this.offset = 0;
this.scopes = new Queue<number>();
this.scopes.push(0);
diff --git a/packages/utils/src/abi_encoder/data_type.ts b/packages/utils/src/abi_encoder/data_type.ts
index 3b4028abd..f5a8087ea 100644
--- a/packages/utils/src/abi_encoder/data_type.ts
+++ b/packages/utils/src/abi_encoder/data_type.ts
@@ -6,7 +6,7 @@ import ethUtil = require('ethereumjs-util');
var _ = require('lodash');
export interface DataTypeFactory {
- create: (dataItem: DataItem, parentDataType: DataType) => DataType;
+ create: (dataItem: DataItem, parentDataType?: DataType) => DataType;
mapDataItemToDataType: (dataItem: DataItem) => DataType;
}
diff --git a/packages/utils/src/abi_encoder/evm_data_types.ts b/packages/utils/src/abi_encoder/evm_data_types.ts
index 2973596fe..d024a9bfa 100644
--- a/packages/utils/src/abi_encoder/evm_data_types.ts
+++ b/packages/utils/src/abi_encoder/evm_data_types.ts
@@ -106,7 +106,8 @@ abstract class Number extends PayloadDataType {
}
}
- public encodeValue(value: BigNumber): Buffer {
+ public encodeValue(value_: BigNumber | string | number): Buffer {
+ const value = new BigNumber(value_, 10);
if (value.greaterThan(this.getMaxValue())) {
throw `tried to assign value of ${value}, which exceeds max value of ${this.getMaxValue()}`;
} else if (value.lessThan(this.getMinValue())) {
@@ -465,6 +466,7 @@ export class SolArray extends MemberDataType {
export class Method extends MemberDataType {
private methodSignature: string;
private methodSelector: string;
+ private returnDataTypes: DataType[];
// TMP
public selector: string;
@@ -473,7 +475,11 @@ export class Method extends MemberDataType {
super({ type: 'method', name: abi.name, components: abi.inputs }, EvmDataTypeFactory.getInstance());
this.methodSignature = this.computeSignature();
this.selector = this.methodSelector = this.computeSelector();
-
+ this.returnDataTypes = [];
+ const dummy = new Byte({ type: 'byte', name: 'DUMMY' }); // @TODO TMP
+ _.each(abi.outputs, (dataItem: DataItem) => {
+ this.returnDataTypes.push(this.getFactory().create(dataItem, dummy));
+ });
}
private computeSignature(): string {
@@ -501,6 +507,23 @@ export class Method extends MemberDataType {
return value;
}
+ public decodeReturnValues(returndata: string, rules?: DecodingRules): any {
+ //console.log('O'.repeat(100), '\n', returndata, '\n', this.returnDataTypes, 'P'.repeat(100));
+
+ const returnValues: any[] = [];
+ const rules_ = rules ? rules : { structsAsObjects: false } as DecodingRules;
+ const rawReturnData = new RawCalldata(returndata, false);
+ _.each(this.returnDataTypes, (dataType: DataType) => {
+ returnValues.push(dataType.generateValue(rawReturnData, rules_));
+ });
+
+ //console.log('*'.repeat(40), '\n', JSON.stringify(returnValues), '\n', '*'.repeat(100));
+ /*if (returnValues.length === 1) {
+ return returnValues[0];
+ }*/
+ return returnValues;
+ }
+
public getSignature(): string {
return this.methodSignature;
}
@@ -538,12 +561,15 @@ export class EvmDataTypeFactory implements DataTypeFactory {
throw new Error(`Unrecognized data type: '${dataItem.type}'`);
}
- public create(dataItem: DataItem, parentDataType: DataType): DataType {
+ public create(dataItem: DataItem, parentDataType?: DataType): DataType {
const dataType = this.mapDataItemToDataType(dataItem);
if (dataType.isStatic()) {
return dataType;
}
+ if (parentDataType === undefined) { // @Todo -- will this work for return values?
+ throw new Error(`Trying to create a pointer`);
+ }
const pointer = new Pointer(dataType, parentDataType);
return pointer;
}
diff --git a/packages/utils/test/abi_encoder_test.ts b/packages/utils/test/abi_encoder_test.ts
index 8d78b61b5..8add41af6 100644
--- a/packages/utils/test/abi_encoder_test.ts
+++ b/packages/utils/test/abi_encoder_test.ts
@@ -15,6 +15,35 @@ describe.only('ABI Encoder', () => {
describe.only('ABI Tests at Method Level', () => {
+ it.only('Should reuse duplicated strings in string array', async () => {
+ const method = new AbiEncoder.Method(AbiSamples.GAbi);
+
+ const args = [
+ {
+ a: new BigNumber(5),
+ e: '0x616161',
+ b: 'aaa',
+ f: '0xe41d2489571d322189246dafa5ebde1f4699f498'
+ }
+ ]
+
+ // Verify optimized calldata is expected
+ const optimizedCalldata = method.encode(args, { optimize: true });
+ //const expectedOptimizedCalldata = '0x13e751a900000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000b5465737420537472696e67000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d5465737420537472696e67203200000000000000000000000000000000000000';
+ //expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata);
+
+ // Verify args decode properly
+ const decodedArgs = method.decode(optimizedCalldata);
+ const decodedArgsJson = JSON.stringify(decodedArgs);
+ const argsJson = JSON.stringify(args);
+ //expect(decodedArgsJson).to.be.equal(argsJson);
+
+ console.log(method.getSignature());
+ console.log('*'.repeat(100), '\n', method.encode(args, { optimize: true, annotate: true }), '\n', '*'.repeat(100));
+ console.log('*'.repeat(100), '\n', method.encode(args, { optimize: true }), '\n', '*'.repeat(100));
+
+ });
+
it('Should reuse duplicated strings in string array', async () => {
const method = new AbiEncoder.Method(AbiSamples.stringAbi);
const strings = [
diff --git a/packages/utils/test/abi_samples.ts b/packages/utils/test/abi_samples.ts
index 5e8268f1a..aa38711cd 100644
--- a/packages/utils/test/abi_samples.ts
+++ b/packages/utils/test/abi_samples.ts
@@ -34,6 +34,40 @@ export const stringAbi = {
type: 'function',
} as MethodAbi;
+
+export const GAbi = {
+ constant: false,
+ inputs: [
+ {
+ components: [{
+ name: 'a',
+ type: 'uint256',
+ },
+ {
+ name: 'b',
+ type: 'string',
+ },
+ {
+ name: 'e',
+ type: 'bytes',
+ },
+ {
+ name: 'f',
+ type: 'address',
+ }],
+
+ name: 'f',
+ type: 'tuple',
+
+ }
+ ],
+ name: 'simpleFunction',
+ outputs: [],
+ payable: false,
+ stateMutability: 'nonpayable',
+ type: 'function',
+} as MethodAbi;
+
export const optimizerAbi2 = {
constant: false,
inputs: [