Fixed issue with decoding negative ints with width < 256

This commit is contained in:
Greg Hysen
2018-11-19 10:34:04 -08:00
parent 8a8b904a29
commit 880540f4b8
3 changed files with 244 additions and 236 deletions

View File

@@ -13,9 +13,9 @@ describe.only('ABI Encoder', () => {
});
describe.only('ABI Tests at Method Level', () => {
describe('ABI Tests at Method Level', () => {
it.only('Should reuse duplicated strings in string array', async () => {
it('Should reuse duplicated strings in string array', async () => {
const method = new AbiEncoder.Method(AbiSamples.GAbi);
const args = [
@@ -723,237 +723,244 @@ describe.only('ABI Encoder', () => {
expect(calldata).to.be.equal(expectedCalldata);
});
});
/*
describe('Array', () => {
it('sample', async () => {
const testDataItem = { name: 'testArray', type: 'int[2]' };
const dataType = new AbiEncoder.SolArray(testDataItem);
console.log(JSON.stringify(dataType, null, 4));
console.log('*'.repeat(60));
dataType.assignValue([new BigNumber(5), new BigNumber(6)]);
console.log(JSON.stringify(dataType, null, 4));
const hexValue = dataType.getHexValue();
console.log('*'.repeat(60));
console.log(hexValue);
});
it('sample undefined size', async () => {
const testDataItem = { name: 'testArray', type: 'int[]' };
const dataType = new AbiEncoder.SolArray(testDataItem);
console.log(JSON.stringify(dataType, null, 4));
console.log('*'.repeat(60));
dataType.assignValue([new BigNumber(5), new BigNumber(6)]);
console.log(JSON.stringify(dataType, null, 4));
const hexValue = dataType.getHexValue();
console.log('*'.repeat(60));
console.log(hexValue);
});
it('sample dynamic types', async () => {
const testDataItem = { name: 'testArray', type: 'string[]' };
const dataType = new AbiEncoder.SolArray(testDataItem);
console.log(JSON.stringify(dataType, null, 4));
console.log('*'.repeat(60));
dataType.assignValue(['five', 'six', 'seven']);
console.log(JSON.stringify(dataType, null, 4));
const hexValue = dataType.getHexValue();
console.log('*'.repeat(60));
console.log(hexValue);
const calldata = new AbiEncoder.Calldata('0x01020304', 1);
dataType.bind(calldata, AbiEncoder.CalldataSection.PARAMS);
console.log('*'.repeat(60));
console.log(calldata.getHexValue());
});
describe.only('Array', () => {
it.only('sample', async () => {
// Create DataType object
const testDataItem = { name: 'testArray', type: 'int[2]' };
const dataType = new AbiEncoder.SolArray(testDataItem);
// Construct args to be encoded
const args = [new BigNumber(5), new BigNumber(6)];
// Encode Args and validate result
const encodedArgs = dataType.encode(args);
const expectedEncodedArgs = '0x00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006';
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);
});
describe('Address', () => {
const testAddressDataItem = { name: 'testAddress', type: 'address' };
it('Valid Address', async () => {
const addressDataType = new AbiEncoder.Address(testAddressDataItem);
addressDataType.assignValue('0xe41d2489571d322189246dafa5ebde1f4699f498');
const expectedAbiEncodedAddress = '0x000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498';
console.log(addressDataType.getHexValue());
console.log(expectedAbiEncodedAddress);
expect(addressDataType.getHexValue()).to.be.equal(expectedAbiEncodedAddress);
});
/*
it('sample undefined size', async () => {
const testDataItem = { name: 'testArray', type: 'int[]' };
const dataType = new AbiEncoder.SolArray(testDataItem);
console.log(JSON.stringify(dataType, null, 4));
console.log('*'.repeat(60));
dataType.assignValue([new BigNumber(5), new BigNumber(6)]);
console.log(JSON.stringify(dataType, null, 4));
const hexValue = dataType.getHexValue();
console.log('*'.repeat(60));
console.log(hexValue);
});
describe('Bool', () => {
const testBoolDataItem = { name: 'testBool', type: 'bool' };
it('True', async () => {
const boolDataType = new AbiEncoder.Bool(testBoolDataItem);
boolDataType.assignValue(true);
const expectedAbiEncodedBool = '0x0000000000000000000000000000000000000000000000000000000000000001';
expect(boolDataType.getHexValue()).to.be.equal(expectedAbiEncodedBool);
});
it('False', async () => {
const boolDataType = new AbiEncoder.Bool(testBoolDataItem);
boolDataType.assignValue(false);
const expectedAbiEncodedBool = '0x0000000000000000000000000000000000000000000000000000000000000000';
expect(boolDataType.getHexValue()).to.be.equal(expectedAbiEncodedBool);
});
});
describe('Integer', () => {
const testIntDataItem = { name: 'testInt', type: 'int' };
it('Positive - Base case', async () => {
const intDataType = new AbiEncoder.Int(testIntDataItem);
intDataType.assignValue(new BigNumber(1));
const expectedAbiEncodedInt = '0x0000000000000000000000000000000000000000000000000000000000000001';
expect(intDataType.getHexValue()).to.be.equal(expectedAbiEncodedInt);
});
it('Positive', async () => {
const intDataType = new AbiEncoder.Int(testIntDataItem);
intDataType.assignValue(new BigNumber(437829473));
const expectedAbiEncodedInt = '0x000000000000000000000000000000000000000000000000000000001a18bf61';
expect(intDataType.getHexValue()).to.be.equal(expectedAbiEncodedInt);
});
it('Negative - Base case', async () => {
const intDataType = new AbiEncoder.Int(testIntDataItem);
intDataType.assignValue(new BigNumber(-1));
const expectedAbiEncodedInt = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff';
expect(intDataType.getHexValue()).to.be.equal(expectedAbiEncodedInt);
});
it('Negative', async () => {
const intDataType = new AbiEncoder.Int(testIntDataItem);
intDataType.assignValue(new BigNumber(-437829473));
const expectedAbiEncodedInt = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffe5e7409f';
expect(intDataType.getHexValue()).to.be.equal(expectedAbiEncodedInt);
});
// TODO: Add bounds tests + tests for different widths
});
describe('Unsigned Integer', () => {
const testIntDataItem = { name: 'testUInt', type: 'uint' };
it('Lower Bound', async () => {
const uintDataType = new AbiEncoder.UInt(testIntDataItem);
uintDataType.assignValue(new BigNumber(0));
const expectedAbiEncodedUInt = '0x0000000000000000000000000000000000000000000000000000000000000000';
expect(uintDataType.getHexValue()).to.be.equal(expectedAbiEncodedUInt);
});
it('Base Case', async () => {
const uintDataType = new AbiEncoder.UInt(testIntDataItem);
uintDataType.assignValue(new BigNumber(1));
const expectedAbiEncodedUInt = '0x0000000000000000000000000000000000000000000000000000000000000001';
expect(uintDataType.getHexValue()).to.be.equal(expectedAbiEncodedUInt);
});
it('Random value', async () => {
const uintDataType = new AbiEncoder.UInt(testIntDataItem);
uintDataType.assignValue(new BigNumber(437829473));
const expectedAbiEncodedUInt = '0x000000000000000000000000000000000000000000000000000000001a18bf61';
expect(uintDataType.getHexValue()).to.be.equal(expectedAbiEncodedUInt);
});
// TODO: Add bounds tests + tests for different widths
});
describe('Static Bytes', () => {
it('Byte (padded)', async () => {
const testByteDataItem = { name: 'testStaticBytes', type: 'byte' };
const byteDataType = new AbiEncoder.Byte(testByteDataItem);
byteDataType.assignValue('0x05');
const expectedAbiEncodedByte = '0x0500000000000000000000000000000000000000000000000000000000000000';
expect(byteDataType.getHexValue()).to.be.equal(expectedAbiEncodedByte);
});
it.skip('Byte (no padding)', async () => {
const testByteDataItem = { name: 'testStaticBytes', type: 'byte' };
const byteDataType = new AbiEncoder.Byte(testByteDataItem);
// @TODO: This does not catch the Error
expect(byteDataType.assignValue('0x5')).to.throw();
});
it('Bytes1', async () => {
const testByteDataItem = { name: 'testStaticBytes', type: 'bytes1' };
const byteDataType = new AbiEncoder.Byte(testByteDataItem);
byteDataType.assignValue('0x05');
const expectedAbiEncodedByte = '0x0500000000000000000000000000000000000000000000000000000000000000';
expect(byteDataType.getHexValue()).to.be.equal(expectedAbiEncodedByte);
});
it('Bytes32 (padded)', async () => {
const testByteDataItem = { name: 'testStaticBytes', type: 'bytes32' };
const byteDataType = new AbiEncoder.Byte(testByteDataItem);
byteDataType.assignValue('0x0001020304050607080911121314151617181920212223242526272829303132');
const expectedAbiEncodedByte = '0x0001020304050607080911121314151617181920212223242526272829303132';
expect(byteDataType.getHexValue()).to.be.equal(expectedAbiEncodedByte);
});
it('Bytes32 (unpadded)', async () => {
const testByteDataItem = { name: 'testStaticBytes', type: 'bytes32' };
const byteDataType = new AbiEncoder.Byte(testByteDataItem);
byteDataType.assignValue('0x1a18bf61');
const expectedAbiEncodedByte = '0x1a18bf6100000000000000000000000000000000000000000000000000000000';
expect(byteDataType.getHexValue()).to.be.equal(expectedAbiEncodedByte);
});
it.skip('Bytes32 - Too long', async () => {
const testByteDataItem = { name: 'testStaticBytes', type: 'bytes32' };
const byteDataType = new AbiEncoder.Byte(testByteDataItem);
// @TODO: This does not catch the Error
expect(
byteDataType.assignValue('0x000102030405060708091112131415161718192021222324252627282930313233'),
).to.throw(
`Tried to assign 0x000102030405060708091112131415161718192021222324252627282930313233 (33 bytes), which exceeds max bytes that can be stored in a bytes32`,
);
});
});
describe('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 () => {
const stringDataType = new AbiEncoder.SolString(testStringDataItem);
stringDataType.assignValue('five');
const expectedAbiEncodedString =
'0x00000000000000000000000000000000000000000000000000000000000000046669766500000000000000000000000000000000000000000000000000000000';
console.log(stringDataType.getHexValue());
console.log(expectedAbiEncodedString);
expect(stringDataType.getHexValue()).to.be.equal(expectedAbiEncodedString);
});
it('Greater than 32 bytes', async () => {
const stringDataType = new AbiEncoder.SolString(testStringDataItem);
const testValue = 'a'.repeat(40);
stringDataType.assignValue(testValue);
const expectedAbiEncodedString =
'0x000000000000000000000000000000000000000000000000000000000000002861616161616161616161616161616161616161616161616161616161616161616161616161616161000000000000000000000000000000000000000000000000';
expect(stringDataType.getHexValue()).to.be.equal(expectedAbiEncodedString);
});
it('sample dynamic types', async () => {
const testDataItem = { name: 'testArray', type: 'string[]' };
const dataType = new AbiEncoder.SolArray(testDataItem);
console.log(JSON.stringify(dataType, null, 4));
console.log('*'.repeat(60));
dataType.assignValue(['five', 'six', 'seven']);
console.log(JSON.stringify(dataType, null, 4));
const hexValue = dataType.getHexValue();
console.log('*'.repeat(60));
console.log(hexValue);
const calldata = new AbiEncoder.Calldata('0x01020304', 1);
dataType.bind(calldata, AbiEncoder.CalldataSection.PARAMS);
console.log('*'.repeat(60));
console.log(calldata.getHexValue());
});*/
});
/*
describe('Address', () => {
const testAddressDataItem = { name: 'testAddress', type: 'address' };
it('Valid Address', async () => {
const addressDataType = new AbiEncoder.Address(testAddressDataItem);
addressDataType.assignValue('0xe41d2489571d322189246dafa5ebde1f4699f498');
const expectedAbiEncodedAddress = '0x000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498';
console.log(addressDataType.getHexValue());
console.log(expectedAbiEncodedAddress);
expect(addressDataType.getHexValue()).to.be.equal(expectedAbiEncodedAddress);
});
});
describe('Bool', () => {
const testBoolDataItem = { name: 'testBool', type: 'bool' };
it('True', async () => {
const boolDataType = new AbiEncoder.Bool(testBoolDataItem);
boolDataType.assignValue(true);
const expectedAbiEncodedBool = '0x0000000000000000000000000000000000000000000000000000000000000001';
expect(boolDataType.getHexValue()).to.be.equal(expectedAbiEncodedBool);
});
it('False', async () => {
const boolDataType = new AbiEncoder.Bool(testBoolDataItem);
boolDataType.assignValue(false);
const expectedAbiEncodedBool = '0x0000000000000000000000000000000000000000000000000000000000000000';
expect(boolDataType.getHexValue()).to.be.equal(expectedAbiEncodedBool);
});
});
describe('Integer', () => {
const testIntDataItem = { name: 'testInt', type: 'int' };
it('Positive - Base case', async () => {
const intDataType = new AbiEncoder.Int(testIntDataItem);
intDataType.assignValue(new BigNumber(1));
const expectedAbiEncodedInt = '0x0000000000000000000000000000000000000000000000000000000000000001';
expect(intDataType.getHexValue()).to.be.equal(expectedAbiEncodedInt);
});
it('Positive', async () => {
const intDataType = new AbiEncoder.Int(testIntDataItem);
intDataType.assignValue(new BigNumber(437829473));
const expectedAbiEncodedInt = '0x000000000000000000000000000000000000000000000000000000001a18bf61';
expect(intDataType.getHexValue()).to.be.equal(expectedAbiEncodedInt);
});
it('Negative - Base case', async () => {
const intDataType = new AbiEncoder.Int(testIntDataItem);
intDataType.assignValue(new BigNumber(-1));
const expectedAbiEncodedInt = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff';
expect(intDataType.getHexValue()).to.be.equal(expectedAbiEncodedInt);
});
it('Negative', async () => {
const intDataType = new AbiEncoder.Int(testIntDataItem);
intDataType.assignValue(new BigNumber(-437829473));
const expectedAbiEncodedInt = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffe5e7409f';
expect(intDataType.getHexValue()).to.be.equal(expectedAbiEncodedInt);
});
// TODO: Add bounds tests + tests for different widths
});
describe('Unsigned Integer', () => {
const testIntDataItem = { name: 'testUInt', type: 'uint' };
it('Lower Bound', async () => {
const uintDataType = new AbiEncoder.UInt(testIntDataItem);
uintDataType.assignValue(new BigNumber(0));
const expectedAbiEncodedUInt = '0x0000000000000000000000000000000000000000000000000000000000000000';
expect(uintDataType.getHexValue()).to.be.equal(expectedAbiEncodedUInt);
});
it('Base Case', async () => {
const uintDataType = new AbiEncoder.UInt(testIntDataItem);
uintDataType.assignValue(new BigNumber(1));
const expectedAbiEncodedUInt = '0x0000000000000000000000000000000000000000000000000000000000000001';
expect(uintDataType.getHexValue()).to.be.equal(expectedAbiEncodedUInt);
});
it('Random value', async () => {
const uintDataType = new AbiEncoder.UInt(testIntDataItem);
uintDataType.assignValue(new BigNumber(437829473));
const expectedAbiEncodedUInt = '0x000000000000000000000000000000000000000000000000000000001a18bf61';
expect(uintDataType.getHexValue()).to.be.equal(expectedAbiEncodedUInt);
});
// TODO: Add bounds tests + tests for different widths
});
describe('Static Bytes', () => {
it('Byte (padded)', async () => {
const testByteDataItem = { name: 'testStaticBytes', type: 'byte' };
const byteDataType = new AbiEncoder.Byte(testByteDataItem);
byteDataType.assignValue('0x05');
const expectedAbiEncodedByte = '0x0500000000000000000000000000000000000000000000000000000000000000';
expect(byteDataType.getHexValue()).to.be.equal(expectedAbiEncodedByte);
});
it.skip('Byte (no padding)', async () => {
const testByteDataItem = { name: 'testStaticBytes', type: 'byte' };
const byteDataType = new AbiEncoder.Byte(testByteDataItem);
// @TODO: This does not catch the Error
expect(byteDataType.assignValue('0x5')).to.throw();
});
it('Bytes1', async () => {
const testByteDataItem = { name: 'testStaticBytes', type: 'bytes1' };
const byteDataType = new AbiEncoder.Byte(testByteDataItem);
byteDataType.assignValue('0x05');
const expectedAbiEncodedByte = '0x0500000000000000000000000000000000000000000000000000000000000000';
expect(byteDataType.getHexValue()).to.be.equal(expectedAbiEncodedByte);
});
it('Bytes32 (padded)', async () => {
const testByteDataItem = { name: 'testStaticBytes', type: 'bytes32' };
const byteDataType = new AbiEncoder.Byte(testByteDataItem);
byteDataType.assignValue('0x0001020304050607080911121314151617181920212223242526272829303132');
const expectedAbiEncodedByte = '0x0001020304050607080911121314151617181920212223242526272829303132';
expect(byteDataType.getHexValue()).to.be.equal(expectedAbiEncodedByte);
});
it('Bytes32 (unpadded)', async () => {
const testByteDataItem = { name: 'testStaticBytes', type: 'bytes32' };
const byteDataType = new AbiEncoder.Byte(testByteDataItem);
byteDataType.assignValue('0x1a18bf61');
const expectedAbiEncodedByte = '0x1a18bf6100000000000000000000000000000000000000000000000000000000';
expect(byteDataType.getHexValue()).to.be.equal(expectedAbiEncodedByte);
});
it.skip('Bytes32 - Too long', async () => {
const testByteDataItem = { name: 'testStaticBytes', type: 'bytes32' };
const byteDataType = new AbiEncoder.Byte(testByteDataItem);
// @TODO: This does not catch the Error
expect(
byteDataType.assignValue('0x000102030405060708091112131415161718192021222324252627282930313233'),
).to.throw(
`Tried to assign 0x000102030405060708091112131415161718192021222324252627282930313233 (33 bytes), which exceeds max bytes that can be stored in a bytes32`,
);
});
});
describe('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 () => {
const stringDataType = new AbiEncoder.SolString(testStringDataItem);
stringDataType.assignValue('five');
const expectedAbiEncodedString =
'0x00000000000000000000000000000000000000000000000000000000000000046669766500000000000000000000000000000000000000000000000000000000';
console.log(stringDataType.getHexValue());
console.log(expectedAbiEncodedString);
expect(stringDataType.getHexValue()).to.be.equal(expectedAbiEncodedString);
});
it('Greater than 32 bytes', async () => {
const stringDataType = new AbiEncoder.SolString(testStringDataItem);
const testValue = 'a'.repeat(40);
stringDataType.assignValue(testValue);
const expectedAbiEncodedString =
'0x000000000000000000000000000000000000000000000000000000000000002861616161616161616161616161616161616161616161616161616161616161616161616161616161000000000000000000000000000000000000000000000000';
expect(stringDataType.getHexValue()).to.be.equal(expectedAbiEncodedString);
});
});*/
});