No safeTransferFrom function in ethers.js contract instance?
Asked Answered
D

3

28

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);
Dressmaker answered 7/7, 2021 at 16:29 Comment(8)
Can you share the ABI? And if the contract is deployed on a public network, it's address as well?Les
ABI: pastebin.com/HY8JhzHm I deployed it on local hardhat blockchain.Dressmaker
Ok thanks. The ABI seems fine. Can you also share the JS snippet executing the safeTransferFrom that throws the error?Les
Thanks for the help. Here is a function test script: pastebin.com/UWVSuBrMDressmaker
@PetrHejda Thank you. The problem is solved. I updated the post :)Dressmaker
If needing to connect to a signer object, syntax is as follows: await instance.connect(secondUser)['safeTransferFrom(address,address,uint256)'](owner.address, secondUser.address, 2);Koniology
@Dressmaker you should add your findings as an answer instead of a question updateGlyptodont
To elaborate further, the reason why it is an overloaded function is because when you look at docs.openzeppelin.com/contracts/4.x/api/token/erc721#ERC721 there are two safeTransferFrom functions. Hence, a different way of calling it via ethers.jsBohman
R
21

(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);

Resoluble answered 9/3, 2022 at 1:30 Comment(1)
await contract.connect(user1)["safeTransferFrom(address,address,uint256,bytes)"](user1Addr, user2Addr, tokenId1, "0x");Flews
B
3

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)

Barth answered 27/7, 2022 at 5:24 Comment(1)
@yongknag thank you for mentioning space thing. those little mistakes waste our time a lotRevivify
C
0
contract[""](address_one , address_two ,uint_)
Cholecyst answered 15/4, 2022 at 10:24 Comment(1)
Remember that Stack Overflow isn't just intended to solve the immediate problem, but also to help future readers find solutions to similar problems, which requires understanding the underlying code. This is especially important for members of our community who are beginners, and not familiar with the syntax. Given that, can you edit your answer to include an explanation of what you're doing and why you believe it is the best approach?Tuneful

© 2022 - 2024 — McMap. All rights reserved.