aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/utils/src/abi_encoder/calldata.ts15
-rw-r--r--packages/utils/src/abi_encoder/data_type.ts2
-rw-r--r--packages/utils/src/abi_encoder/evm_data_types.ts13
-rw-r--r--packages/utils/test/abi_encoder_test.ts52
4 files changed, 66 insertions, 16 deletions
diff --git a/packages/utils/src/abi_encoder/calldata.ts b/packages/utils/src/abi_encoder/calldata.ts
index 078767c22..11288064e 100644
--- a/packages/utils/src/abi_encoder/calldata.ts
+++ b/packages/utils/src/abi_encoder/calldata.ts
@@ -248,7 +248,7 @@ export class Calldata {
private selector: string;
private rules: EncodingRules;
private sizeInBytes: number;
- private root: MemberCalldataBlock | undefined;
+ private root: CalldataBlock | undefined;
constructor(rules: EncodingRules) {
this.selector = '';
@@ -257,8 +257,17 @@ export class Calldata {
this.root = undefined;
}
- private createQueue(memberBlock: MemberCalldataBlock): Queue<CalldataBlock> {
+ private createQueue(block: CalldataBlock): Queue<CalldataBlock> {
const blockQueue = new Queue<CalldataBlock>();
+
+ // Base Case
+ if (block instanceof MemberCalldataBlock === false) {
+ blockQueue.push(block);
+ return blockQueue;
+ }
+
+ // This is a Member Block
+ const memberBlock = block as MemberCalldataBlock;
_.eachRight(memberBlock.getMembers(), (member: CalldataBlock) => {
if (member instanceof MemberCalldataBlock) {
blockQueue.mergeFront(this.createQueue(member));
@@ -429,7 +438,7 @@ export class Calldata {
return "";
}
- public setRoot(block: MemberCalldataBlock) {
+ public setRoot(block: CalldataBlock) {
this.root = block;
this.sizeInBytes += block.getSizeInBytes();
}
diff --git a/packages/utils/src/abi_encoder/data_type.ts b/packages/utils/src/abi_encoder/data_type.ts
index 022f5621f..0f3cecac5 100644
--- a/packages/utils/src/abi_encoder/data_type.ts
+++ b/packages/utils/src/abi_encoder/data_type.ts
@@ -35,7 +35,7 @@ export abstract class DataType {
const calldata = new Calldata(rules_);
if (selector) calldata.setSelector(selector);
const block = this.generateCalldataBlock(value);
- calldata.setRoot(block as MemberCalldataBlock); // @TODO CHANGE
+ calldata.setRoot(block); // @TODO CHANGE
const calldataHex = calldata.toHexString();
return calldataHex;
}
diff --git a/packages/utils/src/abi_encoder/evm_data_types.ts b/packages/utils/src/abi_encoder/evm_data_types.ts
index bfb2808da..1ee95863b 100644
--- a/packages/utils/src/abi_encoder/evm_data_types.ts
+++ b/packages/utils/src/abi_encoder/evm_data_types.ts
@@ -20,6 +20,8 @@ export interface DataTypeStaticInterface {
export class Address extends PayloadDataType {
private static SIZE_KNOWN_AT_COMPILE_TIME: boolean = true;
+ 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";
constructor(dataItem: DataItem) {
super(dataItem, EvmDataTypeFactory.getInstance(), Address.SIZE_KNOWN_AT_COMPILE_TIME);
@@ -36,9 +38,16 @@ export class Address extends PayloadDataType {
return type === 'address';
}
- public encodeValue(value: boolean): Buffer {
+ public encodeValue(value: string): Buffer {
+ if (value.startsWith('0x') === false) {
+ throw new Error(Address.ERROR_MESSAGE_ADDRESS_MUST_START_WITH_0X);
+ }
+ const valueAsBuffer = ethUtil.toBuffer(value);
+ if (valueAsBuffer.byteLength !== 20) {
+ throw new Error(Address.ERROR_MESSAGE_ADDRESS_MUST_BE_20_BYTES);
+ }
const evmWordWidth = 32;
- const encodedValueBuf = ethUtil.setLengthLeft(ethUtil.toBuffer(value), evmWordWidth);
+ const encodedValueBuf = ethUtil.setLengthLeft(valueAsBuffer, evmWordWidth);
return encodedValueBuf;
}
diff --git a/packages/utils/test/abi_encoder_test.ts b/packages/utils/test/abi_encoder_test.ts
index cf1f0327a..5b341545e 100644
--- a/packages/utils/test/abi_encoder_test.ts
+++ b/packages/utils/test/abi_encoder_test.ts
@@ -725,7 +725,7 @@ describe.only('ABI Encoder', () => {
});
});
- describe('Array', () => {
+ describe.only('Array', () => {
it('Fixed size; Static elements', async () => {
// Create DataType object
const testDataItem = { name: 'testArray', type: 'int[2]' };
@@ -793,6 +793,9 @@ describe.only('ABI Encoder', () => {
const argsAsJson = JSON.stringify(args);
expect(decodedArgsAsJson).to.be.equal(argsAsJson);
});
+
+ // @TODO: Add test that fails if we pass in the wrong number of elements
+ // @TODO: Add test that fails if we pass in an element of incorrecrt type
});
describe.only('Tuple', () => {
@@ -849,22 +852,51 @@ describe.only('ABI Encoder', () => {
const argsAsJson = JSON.stringify(args);
expect(decodedArgsAsJson).to.be.equal(argsAsJson);
});
+
+ // @TODO: Add test that fails if we pass in the wrong number of elements
+ // @TODO: Add test that fails if we pass in arguments in wrong order
});
- /*
- describe('Address', () => {
- const testAddressDataItem = { name: 'testAddress', type: 'address' };
+ describe.only('Address', () => {
it('Valid Address', async () => {
- const addressDataType = new AbiEncoder.Address(testAddressDataItem);
- addressDataType.assignValue('0xe41d2489571d322189246dafa5ebde1f4699f498');
- const expectedAbiEncodedAddress = '0x000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498';
+ // Create DataType object
+ const testDataItem = { name: 'Address', type: 'address' };
+ const dataType = new AbiEncoder.Address(testDataItem);
+ // Construct args to be encoded
+ const args = '0xe41d2489571d322189246dafa5ebde1f4699f498';
+ // Encode Args and validate result
+ const encodedArgs = dataType.encode(args);
+ const expectedEncodedArgs = '0x000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498';
+ expect(encodedArgs).to.be.equal(expectedEncodedArgs);
+ // Decode Encoded Args and validate result
+ const decodedArgs = dataType.decode(encodedArgs);
+ const decodedArgsAsJson = JSON.stringify(decodedArgs);
+ const argsAsJson = JSON.stringify(args);
+ expect(decodedArgsAsJson).to.be.equal(argsAsJson);
+ });
- console.log(addressDataType.getHexValue());
- console.log(expectedAbiEncodedAddress);
- expect(addressDataType.getHexValue()).to.be.equal(expectedAbiEncodedAddress);
+ it('Invalid Address - input is not valid hex', async () => {
+ // Create DataType object
+ const testDataItem = { name: 'Address', type: 'address' };
+ const dataType = new AbiEncoder.Address(testDataItem);
+ // Construct args to be encoded
+ const args = 'e4';
+ // Encode Args and validate result
+ expect(() => { dataType.encode(args) }).to.throw(AbiEncoder.Address.ERROR_MESSAGE_ADDRESS_MUST_START_WITH_0X);
+ });
+
+ it('Invalid Address - input is not 20 bytes', async () => {
+ // Create DataType object
+ const testDataItem = { name: 'Address', type: 'address' };
+ const dataType = new AbiEncoder.Address(testDataItem);
+ // Construct args to be encoded
+ const args = '0xe4';
+ // Encode Args and validate result
+ expect(() => { dataType.encode(args) }).to.throw(AbiEncoder.Address.ERROR_MESSAGE_ADDRESS_MUST_BE_20_BYTES);
});
});
+ /*
describe('Bool', () => {
const testBoolDataItem = { name: 'testBool', type: 'bool' };
it('True', async () => {