在 ethers.js 合约实例中没有 safeTransferFrom 函数?

27

我在Hardhat控制台中创建了一个合约实例,如下所示:

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

除了safeTransferFrom之外,合约对象具有所有public/external函数。为什么?

当我使用contract.safeTransferFrom(…)调用它时,它会抛出JavaScript错误“safeTransferFrom不是一个函数”。这是一个bug还是我没有理解其中的一些东西?safeTransferFrom函数在ABI中列出。

我使用未更改的OpenZeppelin(v. 4.2)721令牌模板、Ethers.js(v. 5.4.1)和hardhat(v. 2.4.1)。

更新: 问题已解决。safeTransferFrom是一个重载函数。在ethers中,调用重载的合约函数的语法与非重载函数的语法不同。 Ethers.js文档

错误:

contract.safeTransferFrom(addr1, addr2, 1);

正确:

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

你能分享ABI吗?如果合约部署在公共网络上,也请提供它的地址。 - Petr Hejda
1
好的,谢谢。ABI看起来没问题。你能分享一下执行safeTransferFrom时抛出错误的JS代码片段吗? - Petr Hejda
感谢您的帮助。这是一个函数测试脚本:https://pastebin.com/UWVSuBrM - Lightstorm
@PetrHejda 谢谢。问题已解决。我更新了帖子 :) - Lightstorm
1
@Lightstorm,你应该将你的发现作为答案添加,而不是一个问题更新。 - Jasperan
显示剩余3条评论
3个回答

19

(从@Lightstorm的编辑中复制以确保答案清晰)


safeTransferFrom 是一个重载函数。在 ethers.js 中,调用重载合约函数的语法与调用非重载函数的语法不同。

需要通过指定函数签名来调用重载函数。

来自 ethers.js 文档:

// 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');

对于问题中的示例:

错误:

contract.safeTransferFrom(addr1, addr2, 1);

正确:

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


1
等待合约.connect(user1)["safeTransferFrom(address,address,uint256,bytes)"](user1Addr, user2Addr, tokenId1, "0x"); - Russo

3
在Hardhat中,我们面临着类似的问题,由于过载而导致。
解决方案:
    // 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

请记住,如果您在参数之间有空格,则可能会失败。例如(address,address,uint256)


1
@yongknag 感谢您提及空间问题,这些小错误浪费了我们很多时间。 - Sapthaka

0
contract[""](address_one , address_two ,uint_)

2
请记住,Stack Overflow 不仅是为了解决当前问题,还要帮助未来的读者找到类似问题的解决方案,这需要理解底层代码。对于我们社区中的初学者和不熟悉语法的成员来说,这尤其重要。鉴于此,能否编辑你的答案,包括你正在做什么以及为什么相信这是最好的方法的解释? - Jeremy Caney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接