Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No safeTransferFrom function in ethers.js contract instance?

I created a contract instance in hardhat console like so:

const contract_fac = await ethers.getContractFactory("ContractName");
const contract = await contract_fac.attach("CONTRACTADDR...");

Contract object has all public/external functions except safeTransferFrom. Why?

When I call it with contract.safeTransferFrom(…) it throws JavaScript Error “safeTransferFrom is not a function”. Is this a bug or do I not understand something? safeTransferFrom function is listed in the ABI.

I use OpenZeppelin (v. 4.2) 721 token template without changes, Ethers.js (v. 5.4.1) and hardhat (v. 2.4.1).

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

Wrong:

contract.safeTransferFrom(addr1, addr2, 1);

Correct:

contract["safeTransferFrom(address,address,uint256)"](addr1, addr2, 1);
like image 870
Lightstorm Avatar asked Jul 07 '21 16:07

Lightstorm


2 Answers

(copying from @Lightstorm's edit for answer clarity)


safeTransferFrom is a overloaded function. In ethers.js, the syntax to call an overloaded contract function is different from the syntax to call a non-overloaded function.

Overloaded functions need to be called by specifying the function signature.

From the ethers.js docs:

// ethers
const abi = [
  "function getMessage(string) public view returns (string)",
  "function getMessage() public view returns (string)"
]
const contract = new ethers.Contract(address, abi, signer);

// for ambiguous functions (two functions with the same
// name), the signature must also be specified
message = await contract['getMessage(string)']('nice');

So for the example in the question:

Wrong:

contract.safeTransferFrom(addr1, addr2, 1);

Correct:

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

like image 82
thatguyintech Avatar answered Nov 25 '22 14:11

thatguyintech


On hardhat, we face similar issue, due to overloading

Solution:

    // Send NFT to another contract
    const basicTransferTx = await basicNFTInstance['safeTransferFrom(address,address,uint256)'](
        owner.address,
        otherContract.address,
        0 // token id
    ); // syntax is as such due to overloaded function

keep in mind that it could fail if you have spaces. i.e (address, address, uint256)

like image 21
chia yongkang Avatar answered Nov 25 '22 14:11

chia yongkang