Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ethereumjs-abi

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ethereumjs-abi - npm Package Compare versions

Comparing version 0.4.0 to 0.5.0

154

lib/index.js

@@ -1,30 +0,43 @@

require('es6-shim');
const utils = require('ethereumjs-util');
const BN = require('bn.js');
const Common = require('./common.js');
const utf8 = require('utf8');
var ABI = function() {
this.common = new Common();
};
// Encode as 256bit two's complement
function toTwos(num) {
if (num.isNeg())
num = new BN('10000000000000000000000000000000000000000000000000000000000000000', 16).isub(num.iabs());
// FIXME: the proper way would be if we have bitwise negation: num.iinv().iaddn(1)
return num;
}
// Convert from short to canonical names
// FIXME: optimise or make this nicer?
function elementaryName(name) {
if (name.startsWith('int['))
return 'int256' + name.slice(4);
else if (name === 'int')
return 'int256';
if (name.startsWith('uint['))
return 'uint256' + name.slice(4);
else if (name === 'uint')
return 'uint256';
else if (name.startsWith('real['))
return 'real128x128' + name.slice(4);
else if (name === 'real')
return 'real128x128';
else if (name.startsWith('ureal['))
return 'ureal128x128' + name.slice(4);
else if (name === 'ureal')
return 'ureal128x128';
return name;
};
// Decode from 256bit two's complement
function fromTwos(num) {
if (num.testn(255)) // top bit set => negative number
num = new BN('10000000000000000000000000000000000000000000000000000000000000000', 16).isub(num).ineg();
// FIXME: the proper way would be if we have bitwise negation: num.iinv().iaddn(1)
return num;
}
function eventID(name, types) {
// FIXME: use node.js util.format?
var sig = name + '(' + types.map(elementaryName).join(',') + ')';
return utils.sha3(new Buffer(sig));
};
function methodID(name, types) {
return eventID(name, types).slice(0, 4);
};
// Parse N from type<N>
function parseTypeN(type) {
return parseInt(/^\D+(\d+)$/.exec(type)[1]);
return parseInt(/^\D+(\d+)$/.exec(type)[1], 10);
}

@@ -35,3 +48,3 @@

var tmp = /^\D+(\d+)x(\d+)$/.exec(type);
return [ parseInt(tmp[1]), parseInt(tmp[2]) ];
return [ parseInt(tmp[1], 10), parseInt(tmp[2], 10) ];
}

@@ -45,3 +58,3 @@

else
return parseInt(tmp);
return parseInt(tmp, 10);
}

@@ -86,3 +99,3 @@

throw new Error('Supplied uint exceeds width: ' + size + ' vs ' + num.bitLength());
return new Buffer(num.toArray('be', 32));
return num.toBuffer('be', 32);
} else if (type.startsWith('int')) {

@@ -95,3 +108,3 @@ var size = parseTypeN(type);

throw new Error('Supplied int exceeds width: ' + size + ' vs ' + num.bitLength());
return new Buffer(toTwos(num).toArray('be', 32));
return num.toTwos(256).toBuffer('be', 32);
}

@@ -145,3 +158,3 @@ // FIXME: support ureal<N>x<M> and real<N>x<M>

throw new Error('Invalid uint<N> width: ' + size);
var num = fromTwos(new BN(arg.slice(0, 32), 16, 'be'));
var num = new BN(arg.slice(0, 32), 16, 'be').fromTwos(256);
if (num.bitLength() > size)

@@ -165,3 +178,3 @@ throw new Error('Decoded uint exceeds width: ' + size + ' vs ' + num.bitLength());

// @args an array of the appropriate values
ABI.prototype.rawEncode = function(name, types, args) {
ABI.rawEncode = function(name, types, args) {
var output = new Buffer(0);

@@ -179,3 +192,3 @@ var data = new Buffer(0);

if (name !== null)
pushOutput(this.common.methodID(name, types));
pushOutput(methodID(name, types));

@@ -185,3 +198,3 @@ const headLength = 32 * types.length;

for (var i in types) {
var type = this.common.elementaryName(types[i]);
var type = elementaryName(types[i]);
var arg = args[i];

@@ -203,11 +216,11 @@ var cur = encodeSingle(type, arg);

ABI.prototype.rawEncodeResponse = function(types, args) {
return this.rawEncode(null, types, args);
ABI.rawEncodeResponse = function(types, args) {
return ABI.rawEncode(null, types, args);
};
ABI.prototype.encode = function(abiDefinition, request, args) {
ABI.encode = function(abiDefinition, request, args) {
throw new Error('Not implemented');
};
ABI.prototype.rawDecode = function(name, intypes, outtypes, data) {
ABI.rawDecode = function(name, intypes, outtypes, data) {
var ret = [];

@@ -219,3 +232,3 @@

if (name !== null) {
if (this.common.methodID(name, intypes).toString('hex') !== data.slice(0, 4).toString('hex'))
if (methodID(name, intypes).toString('hex') !== data.slice(0, 4).toString('hex'))
throw new Error('Invalid method signature');

@@ -227,3 +240,3 @@ data = data.slice(4);

for (var i in outtypes) {
var type = this.common.elementaryName(outtypes[i]);
var type = elementaryName(outtypes[i]);
var cur = data.slice(offset, offset + 32);

@@ -250,7 +263,7 @@

ABI.prototype.decode = function(abiDefinition, request, data) {
ABI.decode = function(abiDefinition, request, data) {
throw new Error('Not implemented');
};
ABI.prototype.solidityPack = function(types, values) {
ABI.solidityPack = function(types, values) {
if (types.length !== values.length) {

@@ -261,3 +274,3 @@ throw new Error('Number of types are not matching the values');

for (var i = 0; i < types.length; i++) {
var type = this.common.elementaryName(types[i]);
var type = elementaryName(types[i]);
var value = values[i];

@@ -284,3 +297,3 @@ if (type === 'bytes') {

throw new Error('Supplied uint exceeds width: ' + size + ' vs ' + num.bitLength());
ret.push(utils.pad(num, size / 8));
ret.push(num.toBuffer('be', size / 8));
} else if (type.startsWith('int')) {

@@ -293,3 +306,3 @@ var size = parseTypeN(type);

throw new Error('Supplied int exceeds width: ' + size + ' vs ' + num.bitLength());
ret.push(utils.pad(toTwos(num), size / 8));
ret.push(num.toTwos(size).toBuffer('be', size / 8));
} else {

@@ -303,14 +316,69 @@ // FIXME: support all other types

ABI.prototype.soliditySHA3 = function(types, values) {
return utils.sha3(this.solidityPack(types, values));
ABI.soliditySHA3 = function(types, values) {
return utils.sha3(ABI.solidityPack(types, values));
};
ABI.prototype.soliditySHA256 = function(types, values) {
return utils.sha256(this.solidityPack(types, values));
ABI.soliditySHA256 = function(types, values) {
return utils.sha256(ABI.solidityPack(types, values));
};
ABI.prototype.solidityRIPEMD160 = function(types, values) {
return utils.ripemd160(this.solidityPack(types, values), true);
ABI.solidityRIPEMD160 = function(types, values) {
return utils.ripemd160(ABI.solidityPack(types, values), true);
};
// Serpent's users are familiar with this encoding
// - s: string
// - b: bytes
// - b<N>: bytes<N>
// - i: int256
// - a: int256[]
function isNumeric(c) {
// FIXME: is this correct? Seems to work
return (c >= '0') && (c <= '9');
}
ABI.fromSerpent = function(sig) {
var ret = [];
for (var i = 0; i < sig.length; i++) {
var type = sig[i];
if (type === 's' || type === 'b') {
var tmp = 'bytes';
var j = i + 1;
while ((j < sig.length) && isNumeric(sig[j])) {
tmp += sig[j] - '0';
j++;
}
i = j - 1;
ret.push(tmp);
} else if (type === 'i') {
ret.push('int256');
} else if (type === 'a') {
ret.push('int256[]');
} else {
throw new Error('Unsupported or invalid type: ' + type);
}
}
return ret;
};
ABI.toSerpent = function(types) {
var ret = [];
for (var i = 0; i < types.length; i++) {
var type = types[i];
if (type === 'bytes' || type === 'string') {
ret.push('s');
} else if (type.startsWith('bytes')) {
ret.push('b' + parseTypeN(type));
} else if (type === 'int256') {
ret.push('i');
} else if (type === 'int256[]') {
ret.push('a');
} else {
throw new Error('Unsupported or invalid type: ' + type);
}
}
return ret.join('');
};
module.exports = ABI;
{
"name": "ethereumjs-abi",
"version": "0.4.0",
"version": "0.5.0",
"description": "Decoder and encoder for the Ethereum ABI",
"main": "index.js",
"dependencies": {
"bn.js": "^4.5.2",
"es6-shim": "^0.33.6",
"bn.js": "^4.10.0",
"ethereumjs-util": "^2.3.1",

@@ -10,0 +9,0 @@ "utf8": "2.1.1"

@@ -13,4 +13,3 @@ # ethereumjs-abi

```js
var ABI = require('ethereumjs-abi')
var abi = new ABI()
var abi = require('ethereumjs-abi')

@@ -32,4 +31,3 @@ // returns the encoded binary (as a Buffer) data to be sent

```js
var ABI = require('ethereumjs-abi')
var abi = new ABI()
var abi = require('ethereumjs-abi')

@@ -39,5 +37,5 @@ // need to have the ABI definition in JSON as per specification

var encoded = ABI.encode(tokenAbi, "balanceOf(uint256 address)", [ "0x0000000000000000000000000000000000000000" ])
var encoded = abi.encode(tokenAbi, "balanceOf(uint256 address)", [ "0x0000000000000000000000000000000000000000" ])
var decoded = ABI.decode(tokenAbi, "balanceOf(uint256 address)", data)
var decoded = abi.decode(tokenAbi, "balanceOf(uint256 address)", data)
```

@@ -65,4 +63,3 @@

```js
var ABI = require('ethereumjs-abi')
var abi = new ABI()
var abi = require('ethereumjs-abi')
var BN = require('bn.js')

@@ -83,2 +80,35 @@

#### Using Serpent types
Serpent uses a different notation for the types, even though it will serialize to the same ABI.
We provide two helpers to convert between these notations:
* ```fromSerpent```: convert a Serpent notation to the ABI notation
* ```toSerpent```: the other way around
Example usage:
```js
abi.fromSerpent('s') // [ 'string' ]
abi.fromSerpent('b') // [ 'bytes' ]
abi.fromSerpent('i') // [ 'int256' ]
abi.fromSerpent('a') // [ 'int256[]' ]
abi.fromSerpent('b8') // [ 'bytes8' ]
abi.fromSerpent('b8i') // [ 'bytes8', 'int256' ]
abi.toSerpent([ 'string' ]) // 's'
abi.toSerpent([ 'int256' ]) // 'i'
abi.toSerpent([ 'int256[]' ]) // 'a'
abi.toSerpent([ 'bytes' ]) // 'b'
abi.toSerpent([ 'bytes8' ]) // 'b8'
abi.toSerpent([ 'bytes8', 'int256' ]) // 'b8i'
```
It is to be used in conjunction with ```rawEncode``` and ```rawDecode```:
```js
var encoded = abi.rawEncode("balanceOf", abi.fromSerpent("i"), [ "0x0000000000000000000000000000000000000000" ])
var decoded = abi.rawDecode("balanceOf", abi.fromSerpent("i"), abi.fromSerpent("i"), data)
```
## Contributing

@@ -85,0 +115,0 @@

var assert = require('assert');
var ABI = require('../index.js');
var abi = new ABI();
var abi = require('../index.js');
var BN = require('bn.js');

@@ -16,2 +15,3 @@

/*
describe('official test vector 2 (encoding)', function() {

@@ -24,2 +24,3 @@ it('should equal', function() {

});
*/

@@ -380,1 +381,50 @@ describe('official test vector 3 (encoding)', function() {

});
describe('solidity tight packing with small ints', function() {
it('should equal', function() {
var a = abi.soliditySHA3(
[ 'address', 'address', 'int64', 'uint192' ],
[ new BN('43989fb883ba8111221e89123897538475893837', 16), 0, 10000, 1448075779 ]
);
var b = '1c34bbd3d419c05d028a9f13a81a1212e33cb21f4b96ce1310442911c62c6986';
assert.equal(a.toString('hex'), b.toString('hex'));
});
});
describe('converting from serpent types', function() {
it('should equal', function() {
assert.deepEqual(abi.fromSerpent('s'), [ 'bytes' ]);
assert.deepEqual(abi.fromSerpent('b'), [ 'bytes' ]);
assert.deepEqual(abi.fromSerpent('i'), [ 'int256' ]);
assert.deepEqual(abi.fromSerpent('a'), [ 'int256[]' ]);
assert.deepEqual(abi.fromSerpent('b8'), [ 'bytes8' ]);
assert.deepEqual(abi.fromSerpent('b8i'), [ 'bytes8', 'int256' ]);
assert.deepEqual(abi.fromSerpent('b32'), [ 'bytes32' ]);
assert.deepEqual(abi.fromSerpent('b32i'), [ 'bytes32', 'int256' ]);
assert.deepEqual(abi.fromSerpent('sbb8ib8a'), [ 'bytes', 'bytes', 'bytes8', 'int256', 'bytes8', 'int256[]' ]);
assert.throws(function() {
abi.fromSerpent('i8');
});
assert.throws(function() {
abi.fromSerpent('x');
});
});
});
describe('converting to serpent types', function() {
it('should equal', function() {
assert.equal(abi.toSerpent([ 'string' ]), 's');
assert.equal(abi.toSerpent([ 'int256' ]), 'i');
assert.equal(abi.toSerpent([ 'int256[]' ]), 'a');
assert.equal(abi.toSerpent([ 'bytes' ]), 's');
assert.equal(abi.toSerpent([ 'bytes8' ]), 'b8');
assert.equal(abi.toSerpent([ 'bytes32' ]), 'b32');
assert.equal(abi.toSerpent([ 'string', 'bytes', 'bytes8', 'int256', 'bytes8', 'int256[]' ]), 'ssb8ib8a');
assert.throws(function() {
abi.toSerpent('int8');
});
assert.throws(function() {
abi.toSerpent('bool');
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc