Tron链下使用Tronbox编译OpenZeppelin ERC721合约失败求助
问题描述
我正在使用Solidity和Tronbox学习Tron链智能合约开发,尝试创建ERC721代币时遇到编译失败问题。此前我参照OpenZeppelin官方文档已成功编写过简单的ERC20.sol合约,但使用同官方文档的ERC721合约时出现报错。
报错信息如下:
TypeError: Member "isContract" not unique after argument-dependent lookup in address. --> @openzeppelin/contracts/token/ERC721/ERC721.sol:375:13: | 375 | if (to.isContract()) { | ^^^^^^^^^^^^^ Compilation failed. See above.
我最初怀疑是Solidity版本适配问题,多次切换Solidity版本并安装对应适配的OpenZeppelin版本后,更换不同OpenZeppelin版本仍出现相同报错。
当前开发环境配置
Ubuntu 20.04 tronbox version Tronbox v2.7.23 Solidity v0.8.0 (tron-solc) @openzeppelin/contracts 4.2.0 tronbox$ tail -n7 tronbox.js compilers: { solc: { version: '0.8.0' } } } }
完整编译执行输出
tronbox$ tronbox compile --network development Compiling ./contracts/GameItem.sol... Compiling ./contracts/Migrations.sol... Compiling @openzeppelin/contracts/token/ERC721/ERC721.sol... Compiling @openzeppelin/contracts/token/ERC721/IERC721.sol... Compiling @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol... Compiling @openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol... Compiling @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol... Compiling @openzeppelin/contracts/utils/Address.sol... Compiling @openzeppelin/contracts/utils/Context.sol... Compiling @openzeppelin/contracts/utils/Counters.sol... Compiling @openzeppelin/contracts/utils/Strings.sol... Compiling @openzeppelin/contracts/utils/introspection/ERC165.sol... Compiling @openzeppelin/contracts/utils/introspection/IERC165.sol... TypeError: Member "isContract" not unique after argument-dependent lookup in address. --> @openzeppelin/contracts/token/ERC721/ERC721.sol:375:13: | 375 | if (to.isContract()) { | ^^^^^^^^^^^^^ Compilation failed. See above.
问题解答
根因说明
该报错是tron-solc编译器的特性导致的命名冲突:Tron官方定制的tron-solc编译器内置了address类型的isContract成员方法,而OpenZeppelin的Address工具库也为address类型扩展了同名的isContract方法,两个同名方法同时在作用域生效时,编译器无法判断该调用哪一个,就会抛出成员不唯一的错误。
之前写ERC20合约没有报错,是因为ERC20的实现逻辑里没有用到isContract相关判断,不会触发冲突。
解决方法
可任选以下任意一种方案解决:
- 方案1(最便捷,无需改动环境):修改OpenZeppelin对应源码的调用方式
找到@openzeppelin/contracts/token/ERC721/ERC721.sol文件的第375行,把原代码
替换为显式调用Address库的写法:if (to.isContract()) {
改完直接重新编译即可正常通过。if (Address.isContract(to)) { - 方案2(无需修改第三方库代码):降级OpenZeppelin Contracts版本到3.x系列
3.x版本的ERC721实现没有使用address.isContract()的调用语法,不会触发命名冲突,且3.x系列最高支持Solidity 0.8.0,刚好适配当前的tron-solc版本。 - 方案3(长期适配):升级tronbox和对应tron-solc到最新版本
新版本的tron-solc已经优化了内置方法的命名规则,不会和OpenZeppelin的扩展方法产生冲突,升级后直接编译即可。
内容的提问来源于stack exchange,提问作者Dale Rodel
相关产品推荐
相关产品推荐

