From f35cf030308c0f18ad26669bfb3b269a5b96a39e Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Wed, 7 Nov 2018 13:14:46 -0800 Subject: implemented bytes (dynamic) --- packages/order-utils/test/abi_encoder_test.ts | 121 ++++++++++++++++---------- 1 file changed, 77 insertions(+), 44 deletions(-) diff --git a/packages/order-utils/test/abi_encoder_test.ts b/packages/order-utils/test/abi_encoder_test.ts index 6f723036b..926f7bc81 100644 --- a/packages/order-utils/test/abi_encoder_test.ts +++ b/packages/order-utils/test/abi_encoder_test.ts @@ -528,37 +528,73 @@ namespace AbiEncoder { } } - export class Tuple extends DynamicDataType { + export class Bytes extends StaticDataType { + static UNDEFINED_LENGTH = new BigNumber(-1); + length: BigNumber = SolArray.UNDEFINED_LENGTH; + constructor(dataItem: DataItem) { super(dataItem); - expect(Tuple.matchGrammar(dataItem.type)).to.be.true(); + expect(Bytes.matchGrammar(dataItem.type)).to.be.true(); } - public assignValue(value: string) { - //const hexValue = ethUtil.bufferToHex(new Buffer(value)); - //this.assignHexValue(hexValue); + public assignValue(value: string | Buffer) { + if (typeof value === 'string' && !value.startsWith('0x')) { + throw new Error(`Input value must be hex (prefixed with 0x). Actual value is '${value}'`); + } + const valueBuf = ethUtil.toBuffer(value); + if (value.length % 2 !== 0) { + throw new Error(`Tried to assign ${value}, which is contains a half-byte. Use full bytes only.`); + } + + const wordsForValue = Math.ceil(valueBuf.byteLength / 32); + const paddedBytesForValue = wordsForValue * 32; + const paddedValueBuf = ethUtil.setLengthRight(ethUtil.toBuffer(value), paddedBytesForValue); + const paddedLengthBuf = ethUtil.setLengthLeft(ethUtil.toBuffer(valueBuf.byteLength), 32); + const encodedValueBuf = Buffer.concat([paddedLengthBuf, paddedValueBuf]); + const encodedValue = ethUtil.bufferToHex(encodedValueBuf); + + this.assignHexValue(encodedValue); } public getSignature(): string { - throw 1; + return 'bytes'; } - public encodeToCalldata(calldata: Calldata): void { - throw 2; + public static matchGrammar(type: string): boolean { + return type === 'bytes'; + } + } + + export class SolString extends StaticDataType { + constructor(dataItem: DataItem) { + super(dataItem); + expect(SolString.matchGrammar(dataItem.type)).to.be.true(); + } + + public assignValue(value: string) { + const wordsForValue = Math.ceil(value.length / 32); + const paddedBytesForValue = wordsForValue * 32; + const valueBuf = ethUtil.setLengthRight(ethUtil.toBuffer(value), paddedBytesForValue); + const lengthBuf = ethUtil.setLengthLeft(ethUtil.toBuffer(value.length), 32); + const encodedValueBuf = Buffer.concat([lengthBuf, valueBuf]); + const encodedValue = ethUtil.bufferToHex(encodedValueBuf); + + this.assignHexValue(encodedValue); + } + + public getSignature(): string { + return 'string'; } public static matchGrammar(type: string): boolean { - return type === 'tuple'; + return type === 'string'; } } - export class Bytes extends StaticDataType { - static UNDEFINED_LENGTH = new BigNumber(-1); - length: BigNumber = SolArray.UNDEFINED_LENGTH; - + export class Tuple extends DynamicDataType { constructor(dataItem: DataItem) { super(dataItem); - expect(Bytes.matchGrammar(dataItem.type)).to.be.true(); + expect(Tuple.matchGrammar(dataItem.type)).to.be.true(); } public assignValue(value: string) { @@ -575,7 +611,7 @@ namespace AbiEncoder { } public static matchGrammar(type: string): boolean { - return type === 'bytes'; + return type === 'tuple'; } } @@ -611,34 +647,6 @@ namespace AbiEncoder { } } - export class SolString extends DynamicDataType { - constructor(dataItem: DataItem) { - super(dataItem); - expect(SolString.matchGrammar(dataItem.type)).to.be.true(); - } - - public assignValue(value: string) { - const wordsForValue = Math.ceil(value.length / 32); - const paddedBytesForValue = wordsForValue * 32; - const valueBuf = ethUtil.setLengthRight(ethUtil.toBuffer(value), paddedBytesForValue); - const lengthBuf = ethUtil.setLengthLeft(ethUtil.toBuffer(value.length), 32); - const encodedValueBuf = Buffer.concat([lengthBuf, valueBuf]); - const encodedValue = ethUtil.bufferToHex(encodedValueBuf); - - this.assignHexValue(encodedValue); - } - - public getSignature(): string { - return 'string'; - } - - public encodeToCalldata(calldata: Calldata): void {} - - public static matchGrammar(type: string): boolean { - return type === 'string'; - } - } - /* TODO class Fixed extends StaticDataType {} @@ -906,7 +914,7 @@ describe.only('ABI Encoder', () => { // TODO: Add bounds tests + tests for different widths }); - describe.only('Static Bytes', () => { + describe('Static Bytes', () => { it('Byte (padded)', async () => { const testByteDataItem = { name: 'testStaticBytes', type: 'byte' }; const byteDataType = new AbiEncoder.Byte(testByteDataItem); @@ -960,6 +968,31 @@ describe.only('ABI Encoder', () => { }); }); + describe.only('Bytes (Dynamic)', () => { + const testBytesDataItem = { name: 'testBytes', type: 'bytes' }; + it('Less than 32 bytes', async () => { + const bytesDataType = new AbiEncoder.Bytes(testBytesDataItem); + bytesDataType.assignValue('0x010203'); + const expectedAbiEncodedBytes = + '0x00000000000000000000000000000000000000000000000000000000000000030102030000000000000000000000000000000000000000000000000000000000'; + + expect(bytesDataType.getHexValue()).to.be.equal(expectedAbiEncodedBytes); + }); + + it('Greater than 32 bytes', async () => { + const bytesDataType = new AbiEncoder.Bytes(testBytesDataItem); + const testValue = '0x' + '61'.repeat(40); + bytesDataType.assignValue(testValue); + const expectedAbiEncodedBytes = + '0x000000000000000000000000000000000000000000000000000000000000002861616161616161616161616161616161616161616161616161616161616161616161616161616161000000000000000000000000000000000000000000000000'; + expect(bytesDataType.getHexValue()).to.be.equal(expectedAbiEncodedBytes); + }); + + // @TODO: Add test for throw on half-byte + // @TODO: Test with no 0x prefix + // @TODO: Test with Buffer as input + }); + describe('String', () => { const testStringDataItem = { name: 'testString', type: 'string' }; it('Less than 32 bytes', async () => { -- cgit v1.2.3