From b043832cfdbb5b7bc1dc3b9021bdae82b66be096 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 28 Jul 2015 01:36:32 +0200 Subject: [PATCH] step by step encoding --- lib/solidity/coder.js | 64 +++++++++++++++++++++++++++++++++++---- test/coder.encodeParam.js | 18 +++++++++++ 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/lib/solidity/coder.js b/lib/solidity/coder.js index 0658500..05a07c5 100644 --- a/lib/solidity/coder.js +++ b/lib/solidity/coder.js @@ -100,7 +100,7 @@ SolidityType.prototype.encode = function (value, name) { var nestedName = this.nestedName(name); var result = []; - result.push(f.formatInputInt(length)).encode(); + result.push(f.formatInputInt(length).encode()); var self = this; value.forEach(function (v) { @@ -229,11 +229,11 @@ SolidityCoder.prototype.encodeParams = function (types, params) { var solidityTypes = this.getSolidityTypes(types); var offsets = this.getOffsets(types, solidityTypes); - var encoded = solidityTypes.map(function (solidityType, index) { + var encodeds = solidityTypes.map(function (solidityType, index) { return solidityType.encode(params[index], types[index]); }); - console.log(encoded); + console.log(encodeds); var totalOffset = solidityTypes.reduce(function (acc, solidityType, index) { return acc + solidityType.staticPartLength(types[index]); @@ -241,16 +241,68 @@ SolidityCoder.prototype.encodeParams = function (types, params) { var result = solidityTypes.reduce(function (acc, solidityType, index) { if (solidityType.isDynamicArray(types[index])) { - return acc + f.formatInputInt(offsets[index]).encode(); - } else { - return acc + encoded[index]; + return acc + f.formatInputInt(totalOffset + offsets[index]).encode(); + } else if (solidityType.isStaticArray(types[index])) { + var offset = acc.length / 2; + return acc + encodeds[index].join(''); } + return acc + encodeds[index]; }, ""); + console.log(result); + var self = this; + result = solidityTypes.filter(function (solidityType, index) { + return solidityType.isDynamicArray(types[index]); + }).reduce(function (acc, solidityType, index) { + var offset = acc.length / 2; + return acc + self.encodeWithOffset(types[index], solidityType, encodeds[index], offset); + }, result); + + console.log(result); + return result; }; +SolidityCoder.prototype.encodeWithOffset = function (type, solidityType, encoded, offset) { + if (solidityType.isDynamicArray(type)) { + // offset was already set + var nestedName = solidityType.nestedName(type); + var nestedStaticPartLength = solidityType.staticPartLength(nestedName); + var result = encoded[0]; + + if (solidityType.isDynamicArray(nestedName)) { + for (var i = 0; i < encoded.length; i++) { + result += f.formatInputInt(offset + i * nestedStaticPartLength + encoded.length * 32); + } + } + + // first element is length, skip it + for (var i = 0; i < encoded.length - 1; i++) { + result += this.encodeWithOffset(nestedName, solidityType, encoded[i + 1], offset + i * nestedStaticPartLength); + } + return result; + + } else if (solidityType.isStaticArray(type)) { + var nestedName = solidityType.nestedName(type); + var nestedStaticPartLength = solidityType.staticPartLength(nestedName); + var result = ""; + + if (solidityType.isDynamicArray(nestedName)) { + for (var i = 0; i < encoded.length; i++) { + result += f.formatInputInt(offset + i * nestedStaticPartLength + encoded.length * 32); + } + } + + for (var i = 0; i < encoded.length; i++) { + result += this.encodeWithOffset(nestedName, solidityType, encoded[i], offset + i * nestedStaticPartLength); + } + + return result; + } + + return encoded; +}; /** * Should be used to decode bytes to plain param diff --git a/test/coder.encodeParam.js b/test/coder.encodeParam.js index 43ff681..cea1db0 100644 --- a/test/coder.encodeParam.js +++ b/test/coder.encodeParam.js @@ -14,6 +14,24 @@ describe('lib/solidity/coder', function () { test({ type: 'address', value: '0x407d73d8a49eeb85d32cf465507dd71d507100c1', expected: '000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1'}); + test({ type: 'address[2]', value: ['0x407d73d8a49eeb85d32cf465507dd71d507100c1', '0x407d73d8a49eeb85d32cf465507dd71d507100c3'], + expected: '000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1' + + '000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c3' }); + test({ type: 'address[]', value: ['0x407d73d8a49eeb85d32cf465507dd71d507100c1', '0x407d73d8a49eeb85d32cf465507dd71d507100c3'], + expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000002' + + '000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1' + + '000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c3' }); + //test({ type: 'address[2][]', value: [['0x407d73d8a49eeb85d32cf465507dd71d507100c1', '0x407d73d8a49eeb85d32cf465507dd71d507100c2'], + //['0x407d73d8a49eeb85d32cf465507dd71d507100c3', '0x407d73d8a49eeb85d32cf465507dd71d507100c4']], + //expected: '0000000000000000000000000000000000000000000000000000000000000040' + + //'00000000000000000000000000000000000000000000000000000000000000a0' + + //'0000000000000000000000000000000000000000000000000000000000000002' + [> 40 <] + //'000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1' + [> 60 <] + //'000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c2' + + //'0000000000000000000000000000000000000000000000000000000000000002' + [> a0 <] + //'000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c3' + + //'000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c4' }); //test({ type: 'int', value: 1, expected: '0000000000000000000000000000000000000000000000000000000000000001'}); //test({ type: 'int', value: 16, expected: '0000000000000000000000000000000000000000000000000000000000000010'}); //test({ type: 'int', value: -1, expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'});