5

I've got some data that I need to pack into a single bytes variable. In solidity, it looks like this:

uint16 id = 42;
address creator = '0x...';
uint256 amount = 1337;

bytes memory message = abi.encodePacked(id, creator, amount);

I need to create the same message variable on ethers.js, but I can't find the equivalent of encodePacked in their docs

5 Answers 5

14

I found your solution on the ether.js doc.

It has some functions that would help :

  • ethers.utils.solidityPack( types,values)
  • ethers.utils.solidityKeccak256(types,values)
  • ethers.utils.soliditySha256(types,values)

Solidity Hashing Algorithms sections description says

When using the Solidity abi.packEncoded(...) function, a non-standard tightly packed version of encoding is used. These functions implement the tightly packing algorithm.

https://docs.ethers.io/v5/api/utils/hashing/#utils-solidityPack

1
  • 3
    For anyone looking for an example of how to get the keccack256 hash of an encodePacked(address): console.log(ethers.utils.solidityKeccak256(["address"], ["<your address>"])); Commented Aug 26, 2022 at 21:30
2

In ethers.js, there's a util function can be used https://docs.ethers.io/v5/api/utils/hashing/#utils-solidityPack

so what you need to do here is:

ethers.utils.solidityPack(["uint16", "address", "uint256"], [id, creator, amount])
2

A little snippet i made for ethers.js v6

     import {ethers} from "ethers"

     function encodePacked(params = []){

        let types = []
        let values = []

        params.forEach(itemArray => {
            types.push(itemArray[0])
            values.push(itemArray[1])
        })

        return ethers.solidityPacked(types, values)
      }

Usage:

encodePacked([
  ["string", "Hello"],
  ["uint256", 100]
])
1

abi.encodePacked simply concats together the variables with no padding or length encoding. The equivalent in Javascript is to convert everything to UIntArry8 and concat those together.

const rawMessage = new Uint8Array([
  ...ethers.utils.zeroPad(id, 2),
  ...ethers.utils.arrayify(creator),
  ...ethers.utils.zeroPad(amount, 32)
])

or

const rawMessage = ethers.utils.concat([
  ethers.utils.zeroPad(id, 2), 
  ethers.utils.arrayify(creator),
  ethers.utils.zeroPad(amount, 32)
])
1

Need to implement this line of code

Solidity: keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));

Ethers.js: let encodePacked = ethers.utils.concat([ ethers.utils.toUtf8Bytes('\x19\x01'), ethers.utils.arrayify(DOMAIN_SEPARATOR), ethers.utils.arrayify(structHash) ])

let digest = utils.keccak256(encodePacked)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.