how to pass uint32[], uint8[] parameter to smart contract in web3.js

I'm doing estimateGas. here's my code.

var sdate = new Date('2021-07-01 00:00:00');
var edate = new Date('2021-07-31 00:00:00');
var arrDate = [];
arrDate.push(sdate/1000);
arrDate.push(edate/1000);

var arrCategory = [1,12,14];

var param1 = web3.eth.abi.encodeParameter('uint32[]',arrDate);
var param2 = web3.eth.abi.encodeParameter('uint8[]',arrCategory);

let Contract = new web3.eth.Contract(myPack.abi, myPack.ca);
Contract.methods.createTicket(param1, param2).estimateGas({from: accounts[0]})
  .then(console.log);

and I met error

Uncaught TypeError: t.map is not a function
    at h.formatParam (index.js:218)
    at index.js:100
    at Array.map (<anonymous>)
    at h.encodeParameters (index.js:94)
    at index.js:439
    at Array.map (<anonymous>)
    at Object.d._encodeMethodABI (index.js:438)
    at Object.d._processExecuteArguments (index.js:701)
    at Object.d._executeMethod (index.js:720)
    at estimateGas (issuecfm:257)

I tried something before encodeParameter

BigNumber

var BN =  web3.utils.BN;
arrDate = arrDate.map(item => {return new BN(item)});
arrCategory = arrCategory.map(item => {return new BN(item)});

and String

arrDate = arrDate.map(item => {return item.toString()});
arrCategory = arrCategory.map(item => {return item.toString()});

After a lot of searching, I tried what I could. but I still get the same error. I would really appreciate it if you could teach me how to modify my code.



added

I modified my code like this.

var parameters = web3.eth.abi.encodeParameters(['uint32[]', 'uint8[]'],[arrDate, arrCategory]);
 console.log(parameters);
 console.log(web3.eth.abi.decodeParameters(['uint32[]', 'uint8[]'],parameters));

 let Contract = new web3.eth.Contract(myPack.abi, myPack.ca);
 Contract.methods.createTicket(parameters).estimateGas({from: accounts[0]})
 .then(console.log);


0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000060e31e7000000000000000000000000000000000000000000000000000000000615b16ef0000000000000000000000000000000000000000000000000000000060e31e7000000000000000000000000000000000000000000000000000000000615b16ef000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000011
c {0: Array(4), 1: Array(3), __length__: 2}

I checked that the values ??of parameters are encoded and decoded correctly in the console. &-I

and met next error

errors.js:33 Uncaught Error: Invalid number of parameters for "createTicket". Got 1 expected 2!
    at Object.InvalidNumberOfParams (errors.js:33)
    at Object.d._createTxObject (index.js:670)
    at estimateGas (issuecfm:261)
    at HTMLDocument.<anonymous> (issuecfm:130)
    at j (jquery-latest.min.js:2)
    at Object.fireWith [as resolveWith] (jquery-latest.min.js:2)
    at Function.ready (jquery-latest.min.js:2)
    at HTMLDocument.J (jquery-latest.min.js:2)

Answers 2

  • I believe you have to encode both parameters in an array using the web.eth.abi.encodeParameters() function:

    You pass in an array of types and an array with the values of the parameters like this:

    web3.eth.abi.encodeParameters(['uint32[]','uint8[]'], [arrDate, arrCategory]);
    

    Inside your solidity contract you decode the data like so:

    function createTicket(bytes calldata params) external ... {
        (uint32[] arrDate, uint8[] arrCategory) = abi.decode(params, (uint32[], uint8[]));
    

  • I got a simple solution from stack overflow.

    Using the web3 contract helper function, you need to pass the "raw" JS params, not the ABI-encoded data.

    so I modified my code

    let contract = new web3.eth.Contract(myPack.abi, myPack.ca);
    
    // mind the `arrDate` and `arrCategory` instead of `param1` and `param2`
    contract.methods.createTicket(arrDate, arrCategory)
        .estimateGas({from: accounts[0]})
        .then(console.log);
    

    It works!!


Related Questions