Socket
Socket
Sign inDemoInstall

ethereum-input-data-decoder

Package Overview
Dependencies
107
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.2.1 to 0.3.0

test/data/0x_exchange_data.txt

78

dist/index.js

@@ -5,2 +5,4 @@ 'use strict';

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

@@ -102,3 +104,3 @@

var types = obj.inputs ? obj.inputs.map(function (x) {
if (x.type === 'tuple[]') {
if (x.type.includes('tuple')) {
return x;

@@ -111,4 +113,6 @@ } else {

var names = obj.inputs ? obj.inputs.map(function (x) {
if (x.type === 'tuple[]') {
return '';
if (x.type.includes('tuple')) {
return [x.name, x.components.map(function (a) {
return a.name;
})];
} else {

@@ -128,11 +132,40 @@ return x.name;

} catch (err) {
// TODO: normalize addresses for tuples
inputs = ethers.utils.defaultAbiCoder.decode(types, inputsBuf);
// defaultAbiCoder attaches some unwanted properties to the list object
inputs = deepRemoveUnwantedArrayProperties(inputs);
inputs = inputs[0];
// TODO: do this normalization into normalizeAddresses
inputs = inputs.map(function (input, i) {
if (types[i].components) {
var tupleTypes = types[i].components;
return deepStripTupleAddresses(input, tupleTypes);
}
if (types[i] === 'address') {
return input.split('0x')[1];
}
if (types[i] === 'address[]') {
return input.map(function (address) {
return address.split('0x')[1];
});
}
return input;
});
}
// Map any tuple types into arrays
var typesToReturn = types.map(function (t) {
if (t.components) {
var arr = t.components.reduce(function (acc, cur) {
return [].concat(_toConsumableArray(acc), [cur.type]);
}, []);
var tupleStr = '(' + arr.join(',') + ')';
if (t.type === 'tuple[]') return tupleStr + '[]';
return tupleStr;
}
return t;
});
return {
method: method,
types: types,
types: typesToReturn,
inputs: inputs,

@@ -162,2 +195,27 @@ names: names

// remove 0x from addresses
function deepStripTupleAddresses(input, tupleTypes) {
return input.map(function (item, i) {
var type = tupleTypes[i].type;
if (type === 'address' && typeof item === 'string') {
return item.split('0x')[1];
}
if (type === 'address[]' || Array.isArray()) {
return item.map(function (a) {
return a.split('0x')[1];
});
}
return item;
});
}
function deepRemoveUnwantedArrayProperties(arr) {
return [].concat(_toConsumableArray(arr.map(function (item) {
if (Array.isArray(item)) return deepRemoveUnwantedArrayProperties(item);
return item;
})));
}
function normalizeAddresses(types, input) {

@@ -198,7 +256,5 @@ var offset = 0;

function handleInputs(input) {
var tupleArray = false;
function handleInputs(input, tupleArray) {
if (input instanceof Object && input.components) {
input = input.components;
tupleArray = true;
}

@@ -228,2 +284,4 @@

}
return ret;
}

@@ -233,3 +291,3 @@

var input = methodName + '(' + types.reduce(function (acc, x) {
acc.push(handleInputs(x));
acc.push(handleInputs(x, x.type === 'tuple[]'));
return acc;

@@ -236,0 +294,0 @@ }, []).join(',') + ')';

@@ -86,3 +86,3 @@ const fs = require('fs')

let types = obj.inputs ? obj.inputs.map(x => {
if (x.type === 'tuple[]') {
if (x.type.includes('tuple')) {
return x

@@ -95,4 +95,4 @@ } else {

let names = obj.inputs ? obj.inputs.map(x => {
if (x.type === 'tuple[]') {
return ''
if (x.type.includes('tuple')) {
return [x.name, x.components.map(a => a.name)]
} else {

@@ -112,11 +112,36 @@ return x.name

} catch (err) {
// TODO: normalize addresses for tuples
inputs = ethers.utils.defaultAbiCoder.decode(types, inputsBuf)
// defaultAbiCoder attaches some unwanted properties to the list object
inputs = deepRemoveUnwantedArrayProperties(inputs)
inputs = inputs[0]
// TODO: do this normalization into normalizeAddresses
inputs = inputs.map((input, i) => {
if (types[i].components) {
const tupleTypes = types[i].components
return deepStripTupleAddresses(input, tupleTypes)
}
if (types[i] === 'address') {
return input.split('0x')[1]
}
if (types[i] === 'address[]') {
return input.map(address => address.split('0x')[1])
}
return input
})
}
// Map any tuple types into arrays
const typesToReturn = types.map(t => {
if (t.components) {
const arr = t.components.reduce((acc, cur) => [...acc, cur.type], [])
const tupleStr = `(${arr.join(',')})`
if (t.type === 'tuple[]') return tupleStr + '[]'
return tupleStr
}
return t
})
return {
method,
types,
types: typesToReturn,
inputs,

@@ -143,2 +168,23 @@ names

// remove 0x from addresses
function deepStripTupleAddresses (input, tupleTypes) {
return input.map((item, i) => {
const type = tupleTypes[i].type
if (type === 'address' && typeof item === 'string') {
return item.split('0x')[1]
}
if (type === 'address[]' || Array.isArray()) {
return item.map(a => a.split('0x')[1])
}
return item
})
}
function deepRemoveUnwantedArrayProperties (arr) {
return [...arr.map(item => {
if (Array.isArray(item)) return deepRemoveUnwantedArrayProperties(item)
return item
})]
}
function normalizeAddresses (types, input) {

@@ -179,7 +225,5 @@ let offset = 0

function handleInputs (input) {
let tupleArray = false
function handleInputs (input, tupleArray) {
if (input instanceof Object && input.components) {
input = input.components
tupleArray = true
}

@@ -209,2 +253,4 @@

}
return ret
}

@@ -214,3 +260,3 @@

const input = methodName + '(' + (types.reduce((acc, x) => {
acc.push(handleInputs(x))
acc.push(handleInputs(x, x.type === 'tuple[]'))
return acc

@@ -217,0 +263,0 @@ }, []).join(',')) + ')'

7

package.json
{
"name": "ethereum-input-data-decoder",
"version": "0.2.1",
"version": "0.3.0",
"description": "Ethereum smart contract transaction input data decoder",

@@ -10,5 +10,4 @@ "main": "dist/index.js",

"build": "babel index.js --presets babel-preset-es2015 --out-dir dist/",
"lint": "standard index.js test/*.js",
"lint:fix": "standard --fix index.js test/*.js",
"prepublishOnly": "npm run lint:fix && npm run build"
"lint": "standard --fix index.js test/*.js",
"prepare": "npm run lint && npm run build"
},

@@ -15,0 +14,0 @@ "bin": {

@@ -93,2 +93,32 @@ <h3 align="center">

### Decoding tuple and tuple[] types
Where `OrderData` is
```solidity
struct OrderData {
uint256 amount;
address buyer;
}
```
decoding input to a method `someMethod(address,OrderData,OrderData[])` returns data in format
```js
{
method: 'someMethod',
types: ['address', '(uint256,address)', '(uint256,address)[]'],
inputs: [
'0x81c55017F7Ce6E72451cEd49FF7bAB1e3DF64d0C',
[100, '0xA37dE6790861B5541b0dAa7d0C0e651F44c6f4D9']
[[274, '0xea674fdde714fd979de3edf0f56aa9716b898ec8']]
],
names: ['sender', ['order', ['amount', 'buyer']], ['allOrders', ['amount', 'buyer']]]
}
```
- In the `types` field, tuples are represented as a string containing types contained in the tuple
- In the `inputs` field, tuples are represented as an array containing values contained in the tuple
- In the `names` field, tuples are represented as an array with 2 items. Item 1 is the name of the tuple, item 2 is an array containing the names of the values contained in the tuple.
### Decoding Big Numbers

@@ -217,3 +247,3 @@

```bash
npm run lint:fix
npm run lint
```

@@ -223,4 +253,6 @@

Pull requests are welcome! Fork, branch, and submit PR.
Pull requests are welcome!
For contributions please create a new branch and submit a pull request for review.
## FAQ

@@ -227,0 +259,0 @@

@@ -81,18 +81,137 @@ const fs = require('fs')

t.test('abiv2', t => {
t.plan(5)
// marketSellOrders call
// https://etherscan.io/tx/0xc79ee30142e935453eabd57f45e01bb394bff78d05cdf8df97631b03ad6cc0cd
t.test('0x exchange sell (abiv2 tuple[])', t => {
t.plan(4)
const abi = JSON.parse(fs.readFileSync(`${__dirname}/data/abiv2.json`))
const abi = JSON.parse(fs.readFileSync(`${__dirname}/data/0x_exchange.json`))
const decoder = new InputDataDecoder(abi)
const data = fs.readFileSync(`${__dirname}/data/abiv2_input_data.txt`)
const data = fs.readFileSync(`${__dirname}/data/0x_exchange_data.txt`)
const result = decoder.decodeData(data)
t.equal(result.inputs[0].id.toString(10), '2')
t.equal(result.inputs[0].state.toString(10), '2')
t.equal(result.inputs[0].valuation.toString(10), '50')
t.equal(result.inputs[0].fingerprint.toString(), '0xabcd000000000000000000000000000000000000000000000000000000000000')
t.equal(result.inputs[0].countdown.toString(10), '1549925124')
t.deepEqual(result.method, 'marketSellOrders')
const expectedInputs = [
[
[
'0x6f02E6d47147B4448Fe2f2eb25B4f534cf110c23',
'0x0000000000000000000000000000000000000000',
'0xA258b39954ceF5cB142fd567A46cDdB31a670124',
'0x0000000000000000000000000000000000000000',
{ '_hex': '0x410d586a20a4bffff5' },
{ '_hex': '0x5e05647aedbbd450' },
{ '_hex': '0x00' },
{ '_hex': '0x00' },
{ '_hex': '0x5d787202' },
{ '_hex': '0x016d1e79ae50' },
'0xf47261b000000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359',
'0xf47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'
]
],
{ '_hex': '0x2386f26fc10000' },
[ '0x1b82e97aa18170e6b81ce3a829d77b7067cf3644c8706e97e7c96d5a92de61eb0c5c5aeb4fbfadca6b9fbc5adff91bfb32964aa9e1bf8309dad7e1bd3e45f0b44c03' ]
]
t.deepEqual(result.inputs, expectedInputs)
const expectedTypes = [
'(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[]',
'uint256',
'bytes[]'
]
t.deepEqual(result.types, expectedTypes)
const expectedNames = [
[
'orders',
[
'makerAddress',
'takerAddress',
'feeRecipientAddress',
'senderAddress',
'makerAssetAmount',
'takerAssetAmount',
'makerFee',
'takerFee',
'expirationTimeSeconds',
'salt',
'makerAssetData',
'takerAssetData'
]
],
'takerAssetFillAmount',
'signatures'
]
t.deepEqual(result.names, expectedNames)
})
// https://etherscan.io/tx/0xcb0c447659123c5faa2f1e5bc8ac69697688f437c92a8abb4b882bb33cbc661a
t.test('set issuance (abiv2 tuple)', t => {
t.plan(4)
const abi = JSON.parse(fs.readFileSync(`${__dirname}/data/set_exchange_issuance_lib.json`))
const decoder = new InputDataDecoder(abi)
const data = fs.readFileSync(`${__dirname}/data/set_issuance.txt`)
const result = decoder.decodeData(data)
t.equal(result.method, 'issueRebalancingSetWithEther')
const expectedInputs = [
'81c55017F7Ce6E72451cEd49FF7bAB1e3DF64d0C',
{ '_hex': '0x27019ab6af611240' },
[
'A37dE6790861B5541b0dAa7d0C0e651F44c6f4D9',
{ '_hex': '0x3bf6ab7ba24000' },
[ 1 ],
[ 'C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' ],
[{ '_hex': '0x1a04a045412d3457' }],
[
'89d24A6b4CcB1B6fAA2625fE562bDD9a23260359',
'2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599'
],
[
{ '_hex': '0x06989640c83ea4a200' },
{ '_hex': '0x19c110' }
]
],
'0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000d5a4cdef78c36901bc9ab7c3108c7d7b06f183e7d71c591bb6c677e3fa2958310a2520b916b792c6538b8e43ccb9a1773e94daa441307827c377f3b197d6549f9de54794a806b697a0300000000000000000000000056178a0d5f301baf6cf3e1cd53d9863437345bf90000000000000000000000000acd0b5cf881cd8398ac563872209de1ce15df0f00000000000000000000000055662e225a3376759c24331a9aed764f8f0c9fbb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b70202a2f0d520000000000000000000000000000000000000000000000000000d97e20f757ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005dfa648800000000000000000000000000000000000000000000000015e187ad8bbe980000000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000caa536649a0fdc71bd88fc3a7ecf72f2082e39783296db7a0236b404ca968873f51ce89b4237ecdcf0da1d3cee4306348664629deacaca7f7961ada746036229c5b161612cdb96bad0300000000000000000000000056178a0d5f301baf6cf3e1cd53d9863437345bf90000000000000000000000000acd0b5cf881cd8398ac563872209de1ce15df0f00000000000000000000000055662e225a3376759c24331a9aed764f8f0c9fbb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a38050000000000000000000000000000000000000000000000000ce4d38704d0c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005dfa648800000000000000000000000000000000000000000000000015e187ad8bbe98000000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
true
]
t.deepEqual(result.inputs, expectedInputs)
const expectedNames = [
'_rebalancingSetAddress',
'_rebalancingSetQuantity',
[
'_exchangeIssuanceParams',
[
'setAddress',
'quantity',
'sendTokenExchangeIds',
'sendTokens',
'sendTokenAmounts',
'receiveTokens',
'receiveTokenAmounts'
]
],
'_orderData',
'_keepChangeInVault'
]
t.deepEqual(result.names, expectedNames)
const expectedTypes = [
'address',
'uint256',
'(address,uint256,uint8[],address[],uint256[],address[],uint256[])',
'bytes',
'bool'
]
t.deepEqual(result.types, expectedTypes)
})
// https://github.com/miguelmota/ethereum-input-data-decoder/issues/8

@@ -99,0 +218,0 @@ t.test('256 address', t => {

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc