GithubHelp home page GithubHelp logo

ethereumjs / ethereumjs-abi Goto Github PK

View Code? Open in Web Editor NEW
298.0 14.0 153.0 210 KB

[DEPRECATED] Decoder and encoder for the Ethereum ABI

License: MIT License

JavaScript 100.00%
ethereum abi rpc solidity json

ethereumjs-abi's Introduction

This library is deprecated and will not be further maintained. It specifically doesn't support the new ABI Coder v2 which is now activated by default starting with Solidity v0.8.0 released in December 2020.

We recommend to use the Ethers.js v5 ABI Encoder as a replacement which supports the new ABI Coder v2 types and is under active development.


ethereumjs-abi

NPM Package Build Status Coverage Status js-standard-style Discord

Module implementing the Ethereum ABI in Javascript. Can be used with RPC libraries for communication or with ethereumjs-vm to implement a fully fledged simulator.

Usage

Manual encoding and decoding

There are three methods of interest:

  • methodID to create a function signature
  • rawEncode to encode fields and
  • rawDecode to decode fields

Example code:

var abi = require('ethereumjs-abi')

// returns the encoded binary (as a Buffer) data to be sent
var encoded = abi.rawEncode([ "address" ], [ "0x0000000000000000000000000000000000000000" ])

// returns the decoded array of arguments
var decoded = abi.rawDecode([ "address" ], data)

Encoding and decoding aided by the JSON ABI definition

Planned for the future is supporting the JSON ABI definition:

var abi = require('ethereumjs-abi')

// need to have the ABI definition in JSON as per specification
var tokenAbi = [{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"inputs":[],"type":"constructor"}]

var encoded = abi.encode(tokenAbi, "balanceOf(uint256 address)", [ "0x0000000000000000000000000000000000000000" ])

var decoded = abi.decode(tokenAbi, "balanceOf(uint256 address)", data)

Simple encoding and decoding

var abi = require('ethereumjs-abi')

// returns the encoded binary (as a Buffer) data to be sent
var encoded = abi.simpleEncode("balanceOf(address):(uint256)", "0x0000000000000000000000000000000000000000")

// returns the decoded array of arguments
var decoded = abi.simpleDecode("balanceOf(address):(uint256)", data)

Solidity tightly packed formats

This library also supports creating Solidity's tightly packed data constructs, which are used together with sha3, sha256 and ripemd160 to create hashes.

Solidity code:

contract HashTest {
  function testSha3() returns (bytes32) {
   address addr1 = 0x43989fb883ba8111221e89123897538475893837;
   address addr2 = 0;
   uint val = 10000;
   uint timestamp = 1448075779;

   return sha3(addr1, addr2, val, timestamp); // will return 0xc3ab5ca31a013757f26a88561f0ff5057a97dfcc33f43d6b479abc3ac2d1d595
 }
}

Creating the same hash using this library:

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

abi.soliditySHA3(
    [ "address", "address", "uint", "uint" ],
    [ new BN("43989fb883ba8111221e89123897538475893837", 16), 0, 10000, 1448075779 ]
).toString('hex')

For the same data structure:

  • sha3 will return 0xc3ab5ca31a013757f26a88561f0ff5057a97dfcc33f43d6b479abc3ac2d1d595
  • sha256 will return 0x344d8cb0711672efbdfe991f35943847c1058e1ecf515ff63ad936b91fd16231
  • ripemd160 will return 0x000000000000000000000000a398cc72490f72048efa52c4e92067e8499672e7 (NOTE: it is 160bits, left padded to 256bits)

Note that ripemd160() in Solidity returns bytes20 and if you cast it to bytes32, it will be right padded with zeroes.

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:

abi.fromSerpent('s')    // [ 'bytes' ]
abi.fromSerpent('i')    // [ 'int256' ]
abi.fromSerpent('a')    // [ 'int256[]' ]
abi.fromSerpent('b8')   // [ 'bytes8' ]
abi.fromSerpent('b8i')  // [ 'bytes8', 'int256' ]

abi.toSerpent([ 'bytes' ])             // 's'
abi.toSerpent([ 'int256' ])            // 'i'
abi.toSerpent([ 'int256[]' ])          // 'a'
abi.toSerpent([ 'bytes8' ])            // 'b8'
abi.toSerpent([ 'bytes8', 'int256' ])  // 'b8i'

It is to be used in conjunction with rawEncode and rawDecode:

var encoded = abi.rawEncode(abi.fromSerpent("i"), [ "0x0000000000000000000000000000000000000000" ])

var decoded = abi.rawDecode([...abi.fromSerpent("i"), ...abi.fromSerpent("i")], data)

Note: Serpent uses arbitary binary fields. If you want to store strings it is preferable to ensure it is stored as UTF8. Buffer.from(<string>, 'utf8') can be used to ensure it is properly encoded.

Contributing

I am more than happy to receive improvements. Please send me a pull request or reach out on email or twitter.

There is a lot missing, grep for FIXME in the source code to find inspiration.

EthereumJS

See our organizational documentation for an introduction to EthereumJS as well as information on current standards and best practices.

If you want to join for work or do improvements on the libraries have a look at our contribution guidelines.

License

Copyright (C) 2015 Alex Beregszaszi

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

ethereumjs-abi's People

Contributors

axic avatar djrtwo avatar evertonfraga avatar frozeman avatar gre avatar holgerd77 avatar jag-uk avatar josephdunn avatar michaelmaurer avatar mjmau avatar ritave avatar tinybike avatar yann300 avatar yondonfu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ethereumjs-abi's Issues

Github action ssh permission error on `npm ci`

I am getting this Permission denied error on cypress github action while installing dependencies with the npm ci command

Can not encounter this problem in my local whether I try npm ci or npm i, I am using @cypress/github-action v2.8.4

This is where the error occurs
/usr/bin/git ls-remote -h -t ssh://[email protected]/ethereumjs/ethereumjs-abi.git

This error makes the github actions unusable. Any idea to how solve?

Here is the full log:

/usr/local/bin/npm ci
npm ERR! Error while executing:
npm ERR! /usr/bin/git ls-remote -h -t ssh://[email protected]/ethereumjs/ethereumjs-abi.git
npm ERR! 
npm ERR! Warning: Permanently added the RSA host key for IP address '140.82.113.3' to the list of known hosts.
npm ERR! [email protected]: Permission denied (publickey).
npm ERR! fatal: Could not read from remote repository.
npm ERR! 
npm ERR! Please make sure you have the correct access rights
npm ERR! and the repository exists.
npm ERR! 
npm ERR! exited with error code: 128

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/runner/.npm/_logs/2021-03-26T17_17_00_879Z-debug.log
Error: The process '/usr/local/bin/npm' failed with exit code 1

fromSerpent changes 's' to 'bytes'

In the README it has this example:

abi.fromSerpent('s')    // [ 'string' ]

This is correct. However when I try it, this returns ['bytes'].

Addresses encoded in 32 bytes instead of 20 bytes

In the encodeSingle function, addresses are translated to unit160, so far so good.

Then the recursive call hits the uint-like check and the supplied size (i.e., 160) is retrieved. However, BN's toArrayLike function is called with a fix 32 bytes length. Which is fine, since the EVM operates with this word length, except for the addresses.

@axic Can you confirm whether this is the intended behavior? AFAIK, addresses should be 20 bytes, in which case encodeSingle must retain the information during the recursive call that it's encoding an address (or generally, whether it should respect the parsed size). I don't know how this behavior manifests with more exotic function signatures.

Error HH700: Artifact for contract "Greeter" not found.

I'm new to hardhat and would love to use it inside Docker. However this repo and its instructions fail me at step 8:
docker exec -it myhd yarn deploy:local;

I'm hoping this is a simple fix. I've been searching for hours and thought I'd post an Issue in case this is common. Thanks for your help in advance!

/usr/src/app # yarn deploy:local
yarn run v1.22.19
$ ./node_modules/.bin/hardhat --config hardhat.config.local.js --network localhost my-deploy
Error HH700: Artifact for contract "Greeter" not found.

For more info go to https://hardhat.org/HH700 or run Hardhat with --show-stack-traces
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

not installed

PS C:\Users\Desktop\dex\pancake-frontend-YT--YT> npm install
npm ERR! code ENOENT
npm ERR! syscall spawn git
npm ERR! path git
npm ERR! errno -4058
npm ERR! enoent Error while executing:
npm ERR! enoent undefined ls-remote -h -t https://github.com/ethereumjs/ethereumjs-abi.git
npm ERR! enoent
npm ERR! enoent
npm ERR! enoent spawn git ENOENT
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent

npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\AppData\Roaming\npm-cache_logs\2021-06-22T11_56_47_085Z-debug.log
PS C:\Users\pkgujjar\Desktop\dex\pancake-frontend-YT--YT>

Support 2+D arrays

Currently only 1D arrays are supported. Multiple dimensions are valid in the ABI and others coders support it.

Encoding fixed-size arrays together with the dynamically sized values

abi.rawEncode([ 'bytes', 'uint[2]', 'uint[2]' ], [ 'hello', [1, 2], [3, 4] ])

The code above produces

0000000000000000000000000000000000000000000000000000000000000060
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000000000000000000000000000000000000000000003
0000000000000000000000000000000000000000000000000000000000000004
0000000000000000000000000000000000000000000000000000000000000005
68656c6c6f000000000000000000000000000000000000000000000000000000

Is that the right behaviour? bytes offset here is 96, while it should actually be 160. Correct me if I'm wrong.

Error can not install

Hi,

I am trying to install ethereumjs-abi but always got this issues:
npm ERR! code 1
npm ERR! Command failed: /usr/local/bin/git clone -q https://github.com/ethereumjs/ethereumjs-abi.git /Users/trnhgquan/.npm/_cacache/tmp/git-clone-e6ae2501
npm ERR! /Users/trnhgquan/.npm/_cacache/tmp/git-clone-e6ae2501/.git: Permission denied
npm ERR!

npm ERR! A complete log of this run can be found in:
npm ERR! /Users/trnhgquan/.npm/_logs/2018-08-31T16_15_05_558Z-debug.log

Does anyone here can help me to fix?

Thanks.

Installation problem with sha3 Debian node v4.6

npm ERR! [email protected] install: node-gyp rebuild
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] install script 'node-gyp rebuild'.
npm ERR! This is most likely a problem with the sha3 package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! node-gyp rebuild
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs sha3
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!
npm ERR! npm owner ls sha3
npm ERR! There is likely additional logging output above.

Split monolithic encoder/decoder

Each type should have a simple class with:

  • encode (input: variable type; output: Buffer)
  • decode (input: Buffer; output: variable type)
  • isValid? to check if a parameter can be encoded as the given type

Enable private reporting of vulnerabilities or document how to report vulnerabilities

I wanted to report a security issue, but failed to find a contact. @holgerd77 did not respond to an email I sent. I am aware that this repository is no longer maintained, but first wanted to confirm that posting the issue as GitHub issue is fine.

There are at least two possibilities:

If there is no response to this issue until 21. of August 2023, a GitHub issue about the vulnerability will be created.

Out-of-date handling of `bytes` and `string` arrays -- should this repo be marked as deprecated?

It appears that the ABI spec changed in 2019 or 2020 and this code base has not kept up with it. As a result, all arrays of bytes or string types are encoded incorrectly by this library.

Consider the following toy example with types [ 'bytes[]', 'string[]' ] and values:

[
  [ [ 0x12, 0x34, 0x56, 0x78 ] ],
  [ 'one' ],
]

I have encoded this using ethers and this repo. The results diverge:

ethers:

0000000000000000000000000000000000000000000000000000000000000040    // offset of bytes[] param
00000000000000000000000000000000000000000000000000000000000000c0    // offset of string[] param
0000000000000000000000000000000000000000000000000000000000000001    // number of bytes[] elements
0000000000000000000000000000000000000000000000000000000000000020    // offset of first bytes[] element
0000000000000000000000000000000000000000000000000000000000000004    // size of first bytes[] element
1234567800000000000000000000000000000000000000000000000000000000    // first bytes[] element
0000000000000000000000000000000000000000000000000000000000000001    // number of string[] elements
0000000000000000000000000000000000000000000000000000000000000020    // offset of first string[] element
0000000000000000000000000000000000000000000000000000000000000003    // size of first string[] element
6f6e650000000000000000000000000000000000000000000000000000000000    // first string[] element

ethereumjs-abi:

0000000000000000000000000000000000000000000000000000000000000040    // offset of bytes[] param
00000000000000000000000000000000000000000000000000000000000000a0    // offset of string[] param
0000000000000000000000000000000000000000000000000000000000000001    // number of bytes[] elements
0000000000000000000000000000000000000000000000000000000000000004    // size of first bytes[] element
1234567800000000000000000000000000000000000000000000000000000000    // first bytes[] element
0000000000000000000000000000000000000000000000000000000000000001    // number of string[] elements
0000000000000000000000000000000000000000000000000000000000000003    // size of first string[] element
6f6e650000000000000000000000000000000000000000000000000000000000    // first string[] element

Note the additional offsets for each item in the array params in the ethers result. While I don't understand why the spec changed (there is no new information in the ethers result -- just more data describing offsets that don't seem necessary and pollute blockspace -- but that's none of my business...), I have validated that the ethers result is correct using mainnet transactions with known schema.

Since there have been no new code commits to this repo in 2 years I'm guessing it was abandoned. If that's the case, it would be helpful if you could mark it as deprecated in the README. This would avoid people like me using it as a reference implementation only to learn it was invalid for certain types.

Passing negative numbers to uint/ufixed

Some other tools coerce negative numbers to their two's complement representation when passed to uint.

Should this library do the same?

I'm not entirely convinced it should, because then what should happen with ufixed?

How do I go about running index.js inside test folder

Hi,
I am trying to run the index.js file inside the test folder in order test the application and see how it works. What would be the best way for me run tests. I know a lot of people use truffle or testrpc, beside that how do I go about testing this.
I have all the dependencies installed. I'm new to this so pardon me if this is off topic.

Update package on npm

Lots of bugs still present on the remote npm package, that have been fixed in this repo. Such as any static bytes type immediately returning from the solidityPack method, which is quite an issue!

Please update the npm package to match this repo.

Solidity packing doesn't support arrays

I have been trying to reproduce Solidity's sha3 in Javascript, and have gotten everything to work with my own code except arrays. Once I found out about this library, I tried to use it for arrays, but I haven't been able to get the same hash as Solidity produces yet. It would be great if you might be able to help me understand this better.

How would I generate the same sha3 hash using ethereumjs-abi as in this Solidity example?

contract Contract {
    function Test() constant returns(bytes32) {
        uint[] memory amounts = new uint[](2);
        amounts[0] = 1;
        amounts[1] = 2;

        bytes8[] memory tickers = new bytes8[](2);
        tickers[0] = "BTC";
        tickers[1] = "LTC";

        // 0x4282aea708b799612aa9d311309ef4b8eb1374cf0740c3e9d5914cb5ce9b93f2
        return sha3(amounts, tickers);
    }
}

My attempt gives an error of Cannot read property 1 of undefined:

abi.soliditySHA3(['uint[]', 'bytes8[]'], [[1,2], ['BTC', 'LTC']])

String decoding breaks

Decoding a name() returns (string) breaks.

  Error: Number can only safely store up to 53 bits
      at assert (node_modules/bn.js/lib/bn.js:6:21)
      at BN.toNumber (node_modules/bn.js/lib/bn.js:506:7)
      at decodeSingle (node_modules/ethereumjs-abi/lib/index.js:234:52)
      at decodeSingle (node_modules/ethereumjs-abi/lib/index.js:214:17)
      at Function.ABI.rawDecode (node_modules/ethereumjs-abi/lib/index.js:367:19)
      at app.use (index.js:42:21)
      at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:188:7)

Decoder does not work correctly with fixed-size arrays

The raw output of the function f in the following snippet in browser-solidity is correct:

contract c {
    uint[2] a;
    function f() returns  (uint[2], uint)  {
        a[0] = 1;
        a[1] = 92;
        return (a, 3);
    }
}

But the decoded display shows [[1,92],92].

Decode nested arguments (array of structs)

How to form arguments for rawDecode?

Signature:

marketSellOrders((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],uint256,bytes[])

Data:

0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000006924a03bb710eaf199ab6ac9f2bb148215ae9b5d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a258b39954cef5cb142fd567a46cddb31a67012400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002ce954ae8b5d1cf0000000000000000000000000000000000000000000000036c090d0ca6888000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005d15e7c50000000000000000000000000000000000000000000000000000016b9d8e9ab2000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024f47261b000000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000421b01fda954331f6f5430d93ab7a884458b4b5259e6ce2127e3c41a6090d10481375023f3c61afb372349ec0ecbd0e476593cce90cc8dbb46cf569875910753705403000000000000000000000000000000000000000000000000000000000000

`elliptic/package.json` Module parse failed while using `ethereumjs-abi` with babel/es6

In es6/babel/webpack:

import abi from 'ethereumjs-abi'
./~/elliptic/package.json
Module parse failed: /home/nick/github/cosmo/node_modules/elliptic/package.json Line 2: Unexpected token :
You may need an appropriate loader to handle this file type.
| {
|   "_args": [
|     [
|       "elliptic",
 @ ./~/elliptic/lib/elliptic.js 5:19-45onSocketMsg.errors @ client:47sock.onmessage @ client:82EventTarget.dispatchEvent @ eventtarget.js:49(anonymous function) @ main.js:274SockJS._transportMessage @ main.js:272EventEmitter.emit @ emitter.js:44WebSocketTransport.ws.onmessage @ websocket.js:35

Just reporting this problem here. Looking like a problem with es6/elliptic/babel/webpack. Try using ethereumjs-abi with this webpack/es6/react boilerplate: https://github.com/gaearon/react-hot-boilerplate to recreate the error.

However, when I install just the elliptic package, it seems to build fine in webpack.

Any thoughts on how to proceed? @axic

Define a better public API

This is meant to be a discussion starter for defining a better public API.

Right now, both rawDecode and rawEncode expect an array of argument types as well as array of the values: encode('sampleMethod', [ 'bytes', 'uint' ], [ <bytes data>, 1234 ])

decode and encode was meant to support string definitions matched against the ABI JSON, but it wasn't implemented to date.

What I am thinking about right now for a more user friendly API is:

  • encode('sampleMethod(bytes,uint)', <bytes data>, 1234), and/or
  • encode(abiJSON, 'sampleMethod', <bytes data>, 1234) in this case it is devised that <bytes data> is suitable as bytes type and 1234 as uint type and a matching signature is looked up in the ABI JSON.

(Might need to use actual arrays or fall back to single argument if the signature allows.)

Augur's way:

encode({
  method: 'sampleMethod',
  signature: 'bi',
  params: [ <bytes data>, 1234 ]
})

Perhaps it would be nice to support the Serpent signature, but I am not adamant on it. The Standard Contract ABI page really only refers to the others.

Alternatively there is no need at all for handling the ABI JSON in this project, rather it should be a separate one building on top of an RPC library (perhaps ethrpc) and this one, providing a similar interface to web3.js Contract.

Any ideas?

Length encoding bug when combining dynamic and fixed-size arrays

rawEncode doesn't handle mixed dynamic/fixed arguments correctly.
Example:
simpleEncode("someFunc(string,uint8[5])","xxxx",["1","1","1","1","1"])

should yield
"0x4a0fe00000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000047878787800000000000000000000000000000000000000000000000000000000"

but yields
"0x4a0fe00000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000047878787800000000000000000000000000000000000000000000000000000000"

Proposed solution:

replace rawEncode by

    ABI.rawEncode = function (types, values) {
      var output = []
      var data = []
      var dynLength = []

      var headLength = 0

      for (var i in types) {
        var type = elementaryName(types[i])
        var value = values[i]
        var cur = encodeSingle(type, value)

        // Use the head/tail method for storing dynamic data
        if (isDynamic(type)) {
          output.push(0)
          data.push(cur)
          dynLength.push(cur.length)
          headLength += 32;
        } else {
          output.push(cur)
          dynLength.push(0)
          headLength += cur.length;
        }
      }

      for (var j=0; j< types.length; j++) {
          if (dynLength[j] > 0) {
              output[j] = encodeSingle('uint256', headLength);
              headLength += dynLength[j]
          }
      }

      return Buffer.concat(output.concat(data))
    }

TypeError: abi.encode is not a function

I am using ethereumjs-abi 0.6.5.

I was trying to execute this line of code when the error occured:
ethABI.encode(contractAbi, `${functionName}(${functionParameters})`, value);

Decoded int exceeds width: 160 vs 256

Source code:

const ethabi = require('ethereumjs-abi')
const buf = Buffer.from('85f1150654584d0192059454e9dc1532d9d9cf914926406a02370cea80cf32f6', 'hex')
const res = ethabi.rawDecode(['address'], buf) // fails here
console.log(res)

Console output:

/Users/mota/Sandbox/debug/node_modules/ethereumjs-abi/lib/index.js:242
      throw new Error('Decoded int exceeds width: ' + parsedType.size + ' vs ' + num.bitLength())
      ^

Error: Decoded int exceeds width: 160 vs 256
    at decodeSingle (/Users/mota/Sandbox/debug/node_modules/ethereumjs-abi/lib/index.js:242:13)
    at decodeSingle (/Users/mota/Sandbox/debug/node_modules/ethereumjs-abi/lib/index.js:210:12)
    at Function.ABI.rawDecode (/Users/mota/Sandbox/debug/node_modules/ethereumjs-abi/lib/index.js:367:19)
    at Object.<anonymous> (/Users/mota/Sandbox/debug/index.js:4:20)
    at Module._compile (module.js:660:30)
    at Object.Module._extensions..js (module.js:671:10)
    at Module.load (module.js:573:32)
    at tryModuleLoad (module.js:513:12)
    at Function.Module._load (module.js:505:3)
    at Function.Module.runMain (module.js:701:10)

Transaction data from:

https://etherscan.io/tx/0x0fc8f1cb5112c4679dfcbde54306cabecedfbfd115030252b2e3d77ed7b7da8c

Function: transfer(address _to, uint256 _value)

MethodID: 0xa9059cbb
[0]:  85f1150654584d0192059454e9dc1532d9d9cf914926406a02370cea80cf32f6
[1]:  00000000000000000000000000000000000000000000000000000000033dc10b

method ID:

transfer(address,uint256) => a9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b

Formatting dynamic bytes differs from web3.js

This is more of a question than an issue, but maybe it's an issue. A user informed that when they called a contract function that took in a bytes input, they were getting different results between mycrypto.com and etherscan.com. After some digging in, I determined that we (mycrypto) are using ethereumjs-abi, and etherscan is using web3.js. The way the two encode the same bytes argument seems to be very different:

ethereumjs-abi bytes encoder: https://github.com/ethereumjs/ethereumjs-abi/blob/master/lib/index.js#L136
web3.js bytes encoder: https://github.com/ethereum/web3.js/blob/develop/lib/solidity/formatters.js#L65

Example input:

0xcf2fee595da8d52a6431bead9531b45a33f39db1036cf4fc21018369a93613d43d6f447643bed210ae8b6bac283dadb05a9255db63d7bdaa6662eeaec0bc78d701

ethereumjs-abi output via abi.rawEncode(['bytes'], [input]).toString('hex'):

0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008430786366326665653539356461386435326136343331626561643935333162343561333366333964623130333663663466633231303138333639613933363133643433643666343437363433626564323130616538623662616332383364616462303561393235356462363364376264616136363632656561656330626337386437303100000000000000000000000000000000000000000000000000000000

web3.js output via SolidityCoder.encodeParam('bytes', input):

00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041cf2fee595da8d52a6431bead9531b45a33f39db1036cf4fc21018369a93613d43d6f447643bed210ae8b6bac283dadb05a9255db63d7bdaa6662eeaec0bc78d70100000000000000000000000000000000000000000000000000000000000000

Please let me know if I've made a mistake in how the inputs should be structured, or the output should be converted from a buffer that leads to these differences. Thanks!

Add encode/decode method which accepts argument names

It would be good to return names of named return values, as well as in the future incorporate returning structs: ethereum/EIPs#50

To make that possible we need a function which accepts the full in/outPut types including names, and returns those as object

// returns the encoded binary (as a Buffer) data to be sent
var encoded = abi.typesEncode([ {name: "myNumber", type: "uint256"} ], [ 10 ])
> "0x0000000000000000000000000000000000000000000000000000000000000a"

// returns the decoded array of arguments
var decoded = abi.typesDecode([{name: "myAddress", type: "address"},  {type: "uint256"} ,{name: "myNumber", type: "uint256"}   ], data)
> {
      myAddress: '0x12000000000000000000000000000000000000034',
      0: 5, // if no name is given use indexes
      myNumber: 10
}

The question is only if single return values which have a name, should be returned as objects or the data only.

Structs as described in ethereum/EIPs#50 would be returned the same way, as multiple named return values.

abi.solidityPack does not work with array

> abi.solidityPack(['int32[]', 'bytes8', 'address'], [[0, 0], '0x123456', '0x14723a09acff6d2a60dcdf7aa4aff308fddc160c'])
TypeError: Cannot read property '1' of null
    at parseTypeN (C:\Users\gonglinyuan\node_modules\ethereumjs-abi\lib\index.js:42:42)
    at Function.ABI.solidityPack (C:\Users\gonglinyuan\node_modules\ethereumjs-abi\lib\index.js:467:14)
> abi.solidityPack(['bytes8', 'address'], ['0x123456', '0x14723a09acff6d2a60dcdf7aa4aff308fddc160c'])
<Buffer 12 34 56 00 00 00 00 00 14 72 3a 09 ac ff 6d 2a 60 dc df 7a a4 af f3 08 fd dc 16 0c>

As you can see, solidityPack works perfectly well when there are no array in the parameters. But with 'int32[]', it fails.

Does not work in browser

> EthAbi.rawEncode(["int"], [10])
ethereumjs-abi.js:527 Uncaught Error: Assertion failed(…)assert @ ethereumjs-abi.js:527toBuffer @ ethereumjs-abi.js:1033encodeSingle @ ethereumjs-abi.js:188ABI.rawEncode @ ethereumjs-abi.js:289(anonymous function) @ VM1505:1InjectedScript._evaluateOn @ (program):145InjectedScript._evaluateAndWrap @ (program):137InjectedScript.evaluate @ (program):118

> EthAbi.rawEncode(["string"], ["hi there"])
ethereumjs-abi.js:527 Uncaught Error: Assertion failed(…)assert @ ethereumjs-abi.js:527toBuffer @ ethereumjs-abi.js:1033encodeSingle @ ethereumjs-abi.js:176encodeSingle @ ethereumjs-abi.js:157encodeSingle @ ethereumjs-abi.js:119ABI.rawEncode @ ethereumjs-abi.js:289(anonymous function) @ VM1506:1InjectedScript._evaluateOn @ (program):145InjectedScript._evaluateAndWrap @ (program):137InjectedScript.evaluate @ (program):118

Handle type aliases

I copied types over from my contract and ran into an error when it tried to parse lengths that were missing. The workaround is easy, but it'd be nice if it were safe to copy the types from the contract.

Cannot find module 'ethereumjs-abi'

Running migration: 2_deploy_managers.js
module.js:557
throw err;
^

Error: Cannot find module 'ethereumjs-abi'
at Function.Module._resolveFilename (module.js:555:15)
at Function.Module._load (module.js:482:25)
at Module.require (module.js:604:17)
at require (internal/module.js:11:18)

无法安装

npm WARN tarball tarball data for ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git (null) seems to be corrupted. Trying again.
npm WARN tarball tarball data for ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git (null) seems to be corrupted. Trying again.
npm ERR! code ENOENT
npm ERR! syscall spawn git
npm ERR! path git
npm ERR! errno -4058
npm ERR! enoent An unknown git error occurred
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent

npm ERR! A complete log of this run can be found in: C:\Users\Administrator\AppData\Local\npm-cache_logs\2023-10-07T09_23_55_892Z-debug-0.log

ES6 Shim

Should this library be including the es6-shim? It seems unnecessarily opinionated. I think it would make more sense to leave that decision up to the consumer.

solidity-to-abi: convert a Solidity method interface string to interface ABI object

Heyo, just made this module, you may already have something like this. I just needed a module that did only this. Just some string parsing.

https://www.npmjs.com/package/solidity-to-abi

Usage

import solidityToABI from `solidity-to-abi`;
 
// parse solidity method string 
const abi = solidityToABI('balanceOf(address _addr):(uint256 balance)');
 
console.log(abi);
/*
Object result:
{
  "name": "balanceOf",
  "type": "function",
  "constant": false,
  "inputs": [
    {
      "type": "address",
      "name": "_addr"
    }
  ],
  "outputs": [
    {
      "type": "uint256",
      "name": "balance"
    }
  ]
}
*/

Dynamic array arguments are serialized incorrectly

It looks like the algorithm for nested dynamic arrays got confused with the one for normal dynamic arrays. A normal dynamic array (bool[]) only needs the length of the array to know where the array ends. A nested dynamic array (bool[][3], an array of three dynamic arrays of booleans) needs to know the offsets of the three dynamic arrays so the arrays can be indexed without iterating through the dynamic arrays, so the offset of each dynamic array is packed together at the front of the encoded bytes.

To access the second of the three dynamic arrays, you look up the second offset (the second uint256 of the encoded value) and use that as the offset from the beginning. There, you'll find the length of the second dynamic array followed by the values, just like a non-nested dynamic array.

web3.js also has this bug: web3/web3.js#378

rawEncode silently accepts invalid hex strings

Actual

$ node
> require('ethereumjs-abi').rawEncode(["uint256"], "g")
<Buffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10>

The string "g" gets interpreted as "f"+1.

Expected

Calling rawEncode with invalid number or hex string should throw.

"ethereumjs-abi" not found

When installing [email protected], which depends on ethereumjs-abi, I get this error:

➤ YN0000: ┌ Link step
➤ YN0013: │ ethereumjs-abi@https://github.com/ethereumjs/ethereumjs-abi.git#commit=1cfbb13862f90f0b391d8a699544d5fe4dfb8c7b can't be found in the cache and will be fetched from GitHub
j [HTTPError]: Response code 404 (Not Found)
    at i.<anonymous> (/Users/paulrberg/Projects/Sablier/Magellan/Protocol/.yarn/releases/yarn-berry.js:10:403654)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:97:5) {
  code: undefined,
  timings: undefined
}

I'm using yarn v2, so I'm not sure whether this is an issue with this new experimental version of yarn or ethereumjs-abi.

Error: Cannot find module 'ethereumjs-abi'

specs:

Win 8.1 x64
node 8.0.0
npm 5.0.0

script "constructor_arguments_in_abi.js"

var abi = require('ethereumjs-abi');
var BN = require('bn.js')

parameterTypes = ['address', 'uint256', 'uint256', 'uint256', 'uint256'];
var parameterValues = ['0x123b92c756746da9c264b6e87e7f388c404ea8b8',1507794949,1000000000000000000,32422181682280000000000,32422181682280000000000];

var encoded = abi.rawEncode(parameterTypes, parameterValues);
console.log("Encoded: \n",encoded.toString('hex'));

Prompt console as admin:

C:\projects\ethereum>node constructor_arguments_in_abi.js
module.js:487
    throw err;
    ^

Error: Cannot find module 'ethereumjs-abi'
    at Function.Module._resolveFilename (module.js:485:15)
    at Function.Module._load (module.js:437:25)
    at Module.require (module.js:513:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (C:\projects\ethereum\constructor_arguments_in_abi.js:
41:11)
    at Module._compile (module.js:569:30)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:503:32)
    at tryModuleLoad (module.js:466:12)
    at Function.Module._load (module.js:458:3)

What am I doing wrong?

parseNumber does not properly anticipate BigNumber ... still?

Hey there,

I tried to pack an object which stored values as BigNumber. This failed.

function parseNumber (arg) {
  var type = typeof arg
  if (type === 'string') {
    if (utils.isHexPrefixed(arg)) {
      return new BN(utils.stripHexPrefix(arg), 16)
    } else {
      return new BN(arg, 10)
    }
  } else if (type === 'number') {
    return new BN(arg)
  } else if (arg.toArray) {
    // assume this is a BN for the moment, replace with BN.isBN soon
    return arg
  } else {
    throw new Error('Argument is not a number')
  }
}

Looks like there is some code which tries to guess for BN, but fails to do so properly.

Any intent on fixing this?

soliditySHA3 multiple bytes32 encoding issue

It seems soliditySHA3 does not handle properly case when multiple bytes32 are involved.
Steps to reproduce below:

abi.soliditySHA3([ "bytes32", "bytes32" ], [ "Volume", "Volume" ]).toString('hex');
returns:
8239dae94d559efaf979a8ffdb349ed1d13c6636d28ab641f43ae2bc0c0b985a

Yet,

contract TestTightHash {    
    function coded() constant returns (bytes32) {
        return keccak256(bytes32("Volume"), bytes32("Volume"));
    }
}

coded() returns 0x7ab276f38b269dc879fb051ca72ac238c1a03c2db62bbd7a499c1dd822c3e020

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.