I have a function

function multiERC20TransferTightlyPacked
        ERC20 _token,
        bytes32[] _addressesAndAmounts
    ) public
        for (uint i = 0; i < _addressesAndAmounts.length; i++) {
            address to = address(_addressesAndAmounts[i] >> 96);
            uint amount = uint(uint96(_addressesAndAmounts[i]));
            _safeERC20Transfer(_token, to, amount);
            MultiERC20Transfer(msg.sender, to, amount, _token);

For exmple I want to call this function with _addressesAndAmounts of 0x2970c57fe5264caf1689bc129b41bd7ddf06b4f7 10, and 0x63F69E69857dc198AE63C1BeEe26803c50C00813 10, how can I pass these as parameter to call this function?

  const multisendTx = await contract.methods. multiERC20TransferTightlyPacked(tokenAddress, addressesAmounts).encodeABI();

How should I make the addressesAmounts?

on the solidity code it says:

address to = address(_addressesAndAmounts[i] >> 96);
uint amount = uint(uint96(_addressesAndAmounts[i]));

I don't know what does >> 96 mean how does it work in js?

  • Please specify your web3.js version. Apr 23, 2020 at 7:43
  • Also, from your code, it doesn't look like you need a bytes32 to begin with, since uint256 seems reasonable enough here. Apr 23, 2020 at 7:44
  • I'm using [email protected]
    – bbnn
    Apr 23, 2020 at 7:44
  • what do you mean by that uint256 is reasonable enough?
    – bbnn
    Apr 23, 2020 at 7:45
  • Is this function in your own contract, or in someone else's contract that you need to interact with? Apr 23, 2020 at 7:47

1 Answer 1


You can use this function:

const Web3 = require("web3");

const toBN = Web3.utils.toBN;

function getArray(items) {
    return items.map(item => "0x" + toBN(item.address).shln(96).or(toBN(item.amount)).toString(16));

For example:

const array = getArray([
    {address: "0x2970c57fe5264caf1689bc129b41bd7ddf06b4f7", amount: "10"},
    {address: "0x63F69E69857dc198AE63C1BeEe26803c50C00813", amount: "10"},


The value of amount should be at most 2 ^ 96 - 1 of course.

Its type is string because it can be larger than 2 ^ 53 - 1 (Number.MAX_SAFE_INTEGER).

  • oh so, basically it needs an array of address/amount object, thank you very much, I will try this. and get back to you.
    – bbnn
    Apr 23, 2020 at 8:07
  • @bbnn: No! The contract function takes an array of bytes32 elements. I gave you a JS helper function to create that array. Apr 23, 2020 at 8:08
  • ok, so the array is the addressesAmounts right
    – bbnn
    Apr 23, 2020 at 8:09
  • It's still the same... The transaction got executed successfully with 0 amount value, but reverted with non-0 amount.. I wonder what is wrong.. is there anyway to debug these between executed and execution failure event logs? executed: kovan.etherscan.io/tx/… reverted: kovan.etherscan.io/tx/…
    – bbnn
    Apr 23, 2020 at 9:16
  • @bbnn: Same as what? You asked how to pass a proper input to your contract function, and I gave you an answer. What has that got to do with whether or not the function reverts for some input? There is no such context in your question relating for specific input behavior of the function. If you have a revert issue on some specific input, then I auggest that you post it as a separate question. Apr 23, 2020 at 9:18

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.