[SOLVED] Cannot use safeTransferFrom overloaded function with Moralis.executeFunction

hi! I’m using the new Moralis.executeFunction with ethers.js. Everything works well except this one, using ‘safeTransferFrom’:

      const sendOptions = {
        contractAddress: props.token_address,
        functionName: 'safeTransferFrom',
        abi: JSON.parse(props.token_abi),
        params: {
          from: sender,
          to: receiverAddress.value,
          tokenId: Number(props.token_id),
        }
      }
      try {
        const receipt = await Moralis.executeFunction(sendOptions)

I get the error: contract[functionName] is undefined

Using ‘transferFrom’ works fine. It might be related to the ABI having 2 ‘safeTransferFrom’ methods? It’s standard Openzeppelin ERC721:

and the ABI json:

I will use transferFrom for now, but would be good to tackle this issue.

cheers team Moralis :slight_smile:

1 Like

you can modify the abi that you send as parameter to executeFunction so that it only contains the function that you want to call

ha awesome, so simple :slight_smile:
It does provide some extra challenges, since the ABI for each contract are set in my CMS, so I’ll look into stripping the ABI automatically from that ‘double’ entry in the future. Thanks for using your bright mind this morning!

1 Like

although it does resolve my issue, the solution does feel a bit ‘hacky’.
Using web3.js I had no problems calling this method:

token_contract.methods.safeTransferFrom(sender, receiverAddress.value, props.token_id).send({from: sender})

So it kinda makes the Moralis.executeFunction less good…just my 2 cents, do with it what you will :slight_smile:

1 Like

Update: safeTransferFrom is an overloaded function. In ethers, the syntax to call an overloaded contract function is different from the non-overloaded function. Ethers.js doc

So for using _ethers directly:

Wrong:

contract.safeTransferFrom(addr1, addr2, 1);

Correct:

contract["safeTransferFrom(address,address,uint256)"](addr1, addr2, 1);

I still think that Moralis.executeFunction should be able to handle a ‘standard’ ERC721 ABI without the need to manually remove things from it.

1 Like

would you know how to change the source code for executeFunction so that it can handle overloaded functions?

Sure, i’ve pushed a new branch with a the fix in my fork here:

I’ve added a flag called ‘functionOverload’ to toggle using an ‘overloaded’ contract function, which I use to adjust the functionName to the right format, so including the input type names:

The way to call it is simply by adding functionOverload: true to the sendOptions:

const sendOptions = {
    contractAddress: '0xxxx',
    functionName: 'safeTransferFrom',
    functionOverload: true,
    abi: tokenAbi,
    params: {
      from: '0xxxx',
      to: '0xxxx',
      tokenId: 1,
    }
  }
  await Moralis.executeFunction(sendOptions)

I’ve tested it and it works perfectly this way. Up to you to integrate it the way you want :slight_smile:

To clarify what an overloaded contract function is, here’s part of the pretty standard ERC721 ABI:

    {
      "inputs": [
        {
          "internalType": "address",
          "name": "from",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "tokenId",
          "type": "uint256"
        }
      ],
      "name": "safeTransferFrom",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "from",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "tokenId",
          "type": "uint256"
        },
        {
          "internalType": "bytes",
          "name": "_data",
          "type": "bytes"
        }
      ],
      "name": "safeTransferFrom",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },

And here you can see that there are 2 same functions defined in the contract, but using different params. To keep them apart, you need to use the overloaded format described:

Here’s my commit:

2 Likes

@cryptokid could you let me know when this has been fixed in a new version? Or how I can track it myself? If you want I can do a PL.

I can let you know when it will be fixed, you can also do a pull request if you want

2 Likes

this issues has been solved with Moralis v1.3.1 :partying_face:
Thanks @Erno for the elegant solution!

I’ve tested it, error correction and name suggestion works well.

2 Likes