Skip to content

Commit

Permalink
add encodePacked in web utils (#3701)
Browse files Browse the repository at this point in the history
Co-authored-by: Frankie <frankie.diamond@gmail.com>
Co-authored-by: Gregory Markou <16929357+GregTheGreek@users.noreply.github.com>
  • Loading branch information
3 people authored Sep 2, 2020
1 parent 83691dd commit fb7db14
Show file tree
Hide file tree
Showing 6 changed files with 330 additions and 5 deletions.
1 change: 1 addition & 0 deletions packages/web3-utils/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ module.exports = {
keccak256: utils.sha3,
soliditySha3: soliditySha3.soliditySha3,
soliditySha3Raw: soliditySha3.soliditySha3Raw,
encodePacked: soliditySha3.encodePacked,
isAddress: utils.isAddress,
checkAddressChecksum: utils.checkAddressChecksum,
toChecksumAddress: toChecksumAddress,
Expand Down
25 changes: 21 additions & 4 deletions packages/web3-utils/src/soliditySha3.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ var _solidityPack = function (type, value, arraySize) {
};


var _processSoliditySha3Args = function (arg) {
var _processSolidityEncodePackedArgs = function (arg) {
/*jshint maxcomplexity:false */

if(_.isArray(arg)) {
Expand Down Expand Up @@ -233,7 +233,7 @@ var soliditySha3 = function () {

var args = Array.prototype.slice.call(arguments);

var hexArgs = _.map(args, _processSoliditySha3Args);
var hexArgs = _.map(args, _processSolidityEncodePackedArgs);

// console.log(args, hexArgs);
// console.log('0x'+ hexArgs.join(''));
Expand All @@ -248,11 +248,28 @@ var soliditySha3 = function () {
* @return {Object} the sha3
*/
var soliditySha3Raw = function () {
return utils.sha3Raw('0x'+ _.map(Array.prototype.slice.call(arguments), _processSoliditySha3Args).join(''));
return utils.sha3Raw('0x'+ _.map(Array.prototype.slice.call(arguments), _processSolidityEncodePackedArgs).join(''));
};

/**
* Encode packed args to hex
*
* @method encodePacked
* @return {String} the hex encoded arguments
*/
var encodePacked = function () {
/*jshint maxcomplexity:false */

var args = Array.prototype.slice.call(arguments);

var hexArgs = _.map(args, _processSolidityEncodePackedArgs);

return '0x'+ hexArgs.join('').toLowerCase();
};


module.exports = {
soliditySha3: soliditySha3,
soliditySha3Raw: soliditySha3Raw
soliditySha3Raw: soliditySha3Raw,
encodePacked: encodePacked
};
2 changes: 2 additions & 0 deletions packages/web3-utils/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export function isTopic(topic: string): boolean;
export function jsonInterfaceMethodToString(abiItem: AbiItem): string;
export function soliditySha3(...val: Mixed[]): string | null;
export function soliditySha3Raw(...val: Mixed[]): string;
export function encodePacked(...val: Mixed[]): string | null;
export function getUnitValue(unit: Unit): string;
export function unitMap(): Units;
export function testAddress(bloom: string, address: string): boolean;
Expand Down Expand Up @@ -170,6 +171,7 @@ export interface Utils {
jsonInterfaceMethodToString(abiItem: AbiItem): string;
soliditySha3(...val: Mixed[]): string | null;
soliditySha3Raw(...val: Mixed[]): string;
encodePacked(...val: Mixed[]): string | null;
getUnitValue(unit: Unit): string;
unitMap(): Units;
testAddress(bloom: string, address: string): boolean;
Expand Down
52 changes: 52 additions & 0 deletions packages/web3-utils/types/tests/encode-packed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
This file is part of web3.js.
web3.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
web3.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file solidity-sha3-test.ts
* @author Josh Stevens <joshstevens19@hotmail.co.uk>
* @date 2018
*/

import BN = require('bn.js');
import {encodePacked} from 'web3-utils';

// $ExpectType string | null
encodePacked('234564535', '0xfff23243', true, -10);
// $ExpectType string | null
encodePacked('Hello!%');
// $ExpectType string | null
encodePacked('234');
// $ExpectType string | null
encodePacked(0xea);
// $ExpectType string | null
encodePacked(new BN(3));
// $ExpectType string | null
encodePacked({type: 'uint256', value: '234'});
// $ExpectType string | null
encodePacked({t: 'uint', v: new BN('234')});
// $ExpectType string | null
encodePacked({t: 'string', v: 'Hello!%'}, {t: 'int8', v: -23}, {t: 'address', v: '0x85F43D8a49eeB85d32Cf465507DD71d507100C1d'});
// $ExpectType string | null
encodePacked('0x407D73d8a49eeb85D32Cf465507dd71d507100c1');

// $ExpectError
encodePacked(['hey']);
// $ExpectError
encodePacked([34]);
// $ExpectError
encodePacked(null);
// $ExpectError
encodePacked(undefined);
252 changes: 252 additions & 0 deletions test/utils.encodePacked.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
var _ = require('underscore');
var BN = require('bn.js');
var BigNumber = require('bignumber.js');
var chai = require('chai');
var assert = chai.assert;
var utils = require('../packages/web3-utils');

// each "values" is one kind of parameter of the same type
var tests = [{
values: [
true,
{value: true, type: 'bool'},
{v: true, t: 'bool'},
{v: true, type: 'bool'},
{value: true, t: 'bool'}
], expected: '0x01'
},{
values: [
false,
{value: false, type: 'bool'},
{v: false, t: 'bool'},
{v: false, type: 'bool'},
{value: false, t: 'bool'}
], expected: '0x00'
},{
values: [
'Hello!%',
{value: 'Hello!%', type: 'string'},
{value: 'Hello!%', type: 'string'},
{v: 'Hello!%', t: 'string'}
], expected: '0x48656c6c6f2125'
},{
values: [
2345676856,
'2345676856',
new BN('2345676856'),
new BigNumber('2345676856', 10),
{v: '2345676856', t: 'uint256'},
{v: new BN('2345676856'), t: 'uint256'},
{v: '2345676856', t: 'uint'}
], expected: '0x000000000000000000000000000000000000000000000000000000008bd03038'
},{
values: [
'2342342342342342342345676856',
new BN('2342342342342342342345676856'),
new BigNumber('2342342342342342342345676856', 10),
{v: '2342342342342342342345676856', t: 'uint256'},
{v: '2342342342342342342345676856', t: 'uint'}
], expected: '0x000000000000000000000000000000000000000007918a48d0493ed3da6ed838'
// 5
},{
values: [
{v: '56', t: 'uint8'}
], expected: '0x38'
},{
values: [
{v: '256', t: 'uint16'}
], expected: '0x0100'
},{
values: [
{v: '3256', t: 'uint32'}
], expected: '0x00000cb8'
},{
values: [
{v: '454256', t: 'uint64'}
], expected: '0x000000000006ee70'
},{
values: [
{v: '44454256', t: 'uint128'},
{v: '44454256', t: 'int128'} // should be the same
], expected: '0x00000000000000000000000002a65170'
},{
values: [
{v: '3435454256', t: 'uint160'}
], expected: '0x00000000000000000000000000000000ccc4df30'
// 11
},{
values: [
'0x2345435675432144555ffffffffdd222222222222224444556553522',
{v: '0x2345435675432144555ffffffffdd222222222222224444556553522', t: 'bytes'},
{v: '2345435675432144555ffffffffdd222222222222224444556553522', t: 'bytes'},
{error: true, v: '0x2345435675432144555ffffffffdd22222222222222444455655352', t: 'bytes'}
], expected: '0x2345435675432144555ffffffffdd222222222222224444556553522'
},{
values: [
-3435454256,
new BN(-3435454256),
new BN('-3435454256'),
'-3435454256',
{v: '-3435454256', t: 'int'},
{v: '-3435454256', t: 'int256'}
], expected: '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff333b20d0'
// 13
},{
values: [
{v: '-36', t: 'int8'}
], expected: '0xdc'
},{
values: [
{v: '0x22', t: 'bytes2'},
{v: '22', t: 'bytes2'},
{error: true, v: '0x222222', t: 'bytes2'}
], expected: '0x2200'
},{
values: [
{v: '0x44222266', t: 'bytes4'},
{v: '44222266', t: 'bytes4'}
], expected: '0x44222266'
},{
values: [
{v: '0x44555ffffffffdd222222222222224444556553522', t: 'bytes32'},
{v: '44555ffffffffdd222222222222224444556553522', t: 'bytes32'}
], expected: '0x44555ffffffffdd2222222222222244445565535220000000000000000000000'
},{
values: [
'0x407D73d8a49eeb85D32Cf465507dd71d507100c1',
'0x407d73d8a49eeb85D32Cf465507dd71d507100c1', // invalid checksum, should work as it is interpreted as address
{v: '0x407D73d8a49eeb85D32Cf465507dd71d507100c1', t: 'address'},
{error: true, v: '0x407d73d8a49eeb85D32Cf465507dd71d507100c1', t: 'address'},
{v: '0x407D73d8a49eeb85D32Cf465507dd71d507100c1', t: 'bytes'},
{v: '0x407D73d8a49eeb85D32Cf465507dd71d507100c1', t: 'bytes20'}
], expected: '0x407d73d8a49eeb85d32cf465507dd71d507100c1'
// 18
},{
values: [
{v: '36', t: 'int8'}
], expected: '0x24'
},{
values: [
{v: '36', t: 'int256'}
], expected: '0x0000000000000000000000000000000000000000000000000000000000000024'
},{
values: [
{v: [-12, 243], t: 'int[]'},
{v: [-12, 243], t: 'int256[]'},
{v: ['-12', '243'], t: 'int256[]'},
{v: [new BN('-12'), new BN('243')], t: 'int256[]'},
{v: ['-12', '243'], t: 'int256[2]'}
], expected: '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff400000000000000000000000000000000000000000000000000000000000000f3'
},{
values: [
{v: [12, 243], t: 'uint[]'},
{v: [12, 243], t: 'uint256[]'},
{v: ['12', '243'], t: 'uint256[]'},
{v: [new BN('12'), new BN('243')], t: 'uint256[]'},
{v: ['12', '243'], t: 'uint256[2]'},
{error: true, v: ['12', '243'], t: 'uint256[1]'}
], expected: '0x000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000f3'
},{
values: [
{v: ['0x234656', '0x23434234234ffff456'], t: 'bytes32[]'},
], expected: '0x234656000000000000000000000000000000000000000000000000000000000023434234234ffff4560000000000000000000000000000000000000000000000'
},{
values: [
{v: '0x234656', t: 'bytes16'},
{v: '234656', t: 'bytes16'}
], expected: '0x23465600000000000000000000000000'
},{
values: [
{v: ['0x234656', '0x23434234234ffff456'], t: 'bytes16[]'},
{v: ['234656', '23434234234ffff456'], t: 'bytes16[]'}
], expected: '0x234656000000000000000000000000000000000000000000000000000000000023434234234ffff4560000000000000000000000000000000000000000000000'
},{
values: [
{v: ['0x407D73d8a49eeb85D32Cf465507dd71d507100c1', '0x85F43D8a49eeB85d32Cf465507DD71d507100C1d'], t: 'address[]'},
{v: ['0x407D73d8a49eeb85D32Cf465507dd71d507100c1', '0x85F43D8a49eeB85d32Cf465507DD71d507100C1d'], t: 'address[2]'},
{error: true, v: ['0x407d73d8a49eeb85D32Cf465507dd71d507100c1', '0x85F43D8a49eeB85d32Cf465507DD71d507100C1d'], t: 'address[]'},
{error: true, v: ['0x407D73d8a49eeb85D32Cf465507dd71d507100c1', '0x85F43D8a49eeB85d32Cf465507DD71d507100C1d'], t: 'address[4]'}
], expected: '0x000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c100000000000000000000000085f43d8a49eeb85d32cf465507dd71d507100c1d'
},{
values: [
{v: 0, t: 'uint'}
], expected: '0x0000000000000000000000000000000000000000000000000000000000000000'
},{
values: [
['someValue'] // should error
], expected: ''
}];


describe('web3.encodePacked', function () {
tests.forEach(function (test) {
test.values.forEach(function (value) {
it('should hash "'+ JSON.stringify(value) +'" into "'+ test.expected +'"', function() {

if(value.error || _.isArray(value)) {
assert.throws(utils.encodePacked.bind(null, value));
} else {
assert.deepEqual(utils.encodePacked(value), test.expected);
}

});
});
});

it('should hash mixed boolean values in any order', function() {

assert.deepEqual(utils.encodePacked(
tests[0].values[1], // true
tests[1].values[0], // false
tests[1].values[2], // false
tests[0].values[3] // true
), '0x01000001');
});

it('should hash mixed string and number values in any order', function() {

assert.deepEqual(utils.encodePacked(
tests[2].values[0], // 'Hello!%'
tests[3].values[2], // 2345676856
tests[4].values[2], // '2342342342342342342345676856'
tests[2].values[3], // 'Hello!%'
tests[1].values[2] // false
), '0x48656c6c6f2125000000000000000000000000000000000000000000000000000000008bd03038000000000000000000000000000000000000000007918a48d0493ed3da6ed83848656c6c6f212500');
});

it('should hash mixed number types in any order', function() {

assert.deepEqual(utils.encodePacked(
tests[5].values[0], // v: '56', t: 'uint8'
tests[6].values[0], // v: '256', t: 'uint16'
tests[7].values[0], // v: '3256', t: 'uint32'
tests[8].values[0], // v: '454256', t: 'uint64'
tests[9].values[0], // v: '44454256', t: 'uint128'
tests[10].values[0] // v: '3435454256', t: 'uint160'
), '0x38010000000cb8000000000006ee7000000000000000000000000002a6517000000000000000000000000000000000ccc4df30');
});

it('should hash mixed number types addresses and boolean in any order', function() {

assert.deepEqual(utils.encodePacked(
tests[5].values[0], // v: '56', t: 'uint8'
tests[13].values[0], // v: '-36', t: 'int8'
tests[15].values[0], // v: '0x44222266', t: 'bytes4'
tests[0].values[0], // true
tests[17].values[1] // v: '0x407D73d8a49eeb85D32Cf465507dd71d507100c1', t: 'address'
), '0x38dc4422226601407d73d8a49eeb85d32cf465507dd71d507100c1');
});

it('should hash mixed number arrays addresses and boolean in any order', function() {

assert.deepEqual(utils.encodePacked(
tests[15].values[1], // v: '0x44222266', t: 'bytes4'
tests[25].values[0], // address array
tests[0].values[0], // true
tests[13].values[0], // v: '-36', t: 'int8'
tests[12].values[5], // v: '-3435454256', t: 'int256'
tests[17].values[0], // 0x407D73d8a49eeb85D32Cf465507dd71d507100c1
tests[17].values[1] // v: 0x407D73d8a49eeb85D32Cf465507dd71d507100c1 t: address
), '0x44222266000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c100000000000000000000000085f43d8a49eeb85d32cf465507dd71d507100c1d01dcffffffffffffffffffffffffffffffffffffffffffffffffffffffff333b20d0407d73d8a49eeb85d32cf465507dd71d507100c1407d73d8a49eeb85d32cf465507dd71d507100c1');
});
});
3 changes: 2 additions & 1 deletion test/utils_methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ describe('utils', function() {
u.methodExists(utils, 'toWei');
u.methodExists(utils, 'toBN');
u.methodExists(utils, 'isAddress');
u.methodExists(utils, 'soliditySha3');
u.methodExists(utils, 'encodePacked');
});
});

0 comments on commit fb7db14

Please sign in to comment.