Correct way to pass byte type data to the Smart Contract function?

I’m trying to follow the implementation given here to implement signature verification.

The frontend code returns the following error-
Error: invalid arrayify value (argument="value", value="", code=INVALID_ARGUMENT, version=bytes/5.6.0)

I think this is because of the signature being passed as a string instead of bytes. What’s the best way to pass the signature to the contract’s function?

Solidity Code

struct NFTVoucher {
    uint256 _id;
    uint256 _amount;
    string nuri;
    bytes signature;
 }

function mint(NFTVoucher calldata voucher) payable public  {
    address signer = _verify(voucher);
    _mint(msg.sender,voucher._id, voucher._amount, "");
 }

 function _verify(NFTVoucher calldata voucher) internal view returns (address) {
    bytes32 digest = _hash(voucher);
    return ECDSA.recover(digest, voucher.signature);
 }

function _hash(NFTVoucher calldata voucher) internal view returns (bytes32) {
    return _hashTypedDataV4(keccak256(abi.encode(
      keccak256("NFTVoucher(uint256 _id,uint256 _amount,string nuri)"),
      voucher._id,
      voucher._amount,
      keccak256(bytes(voucher.nuri))
    )));
  }

Javascript Code - Frontend

var voucher = {
          _id: 18,
          _amount: 1,
          nuri: "ipfs://xyz/metadata/14.json",
          signature : signaturefrombackend
        }
        let options = {
            contractAddress: TOKEN_CONTRACT_ADDRESS,
            functionName: "mint",
            abi: ABI,
            params: {
              voucher: voucher,
            },
            //msgValue: Moralis.Units.ETH(0.001),
        };
        const transaction = await Moralis.executeFunction(options);

Backend code to generate signature

var {keccak256} = require("@ethersproject/keccak256");
var {toUtf8Bytes} = require("@ethersproject/strings");

const signature = keccak256(toUtf8Bytes("sampledata"));
//returns string
1 Like

Is there any alternative to the above implementation? I’m doing lazy mint where users passes the uri and other details of the NFT from the database. I suppose this can be manipulated by the user, so signature verification is required.

I would think that you can convert that signature : signaturefrombackend to different formats, first you can try to use console.log(JSON.stringify(signaturefrombackend)) to see that type of data you have there.

you can send it from backend as encoded in base64 or hex encoded and then convert it in front end to bytes or send it directly as hex encoded to the contract and convert it in the contract function to bytes (it should be an easier solution)

@carry_potter Did you managed to pass byte-type data into the executeFunction() ?

What sort of byte data do you need to pass in as params? If it’s empty, you can use an empty string "". Otherwise I think ethers.js has some utility functions that you can use so it’s in the right format.