您如何與 ^0.7.6 合約中的 ^0.4.x ERC721 互動?
在我看來,pre 0.5 NFT 與更現代的 Solidity 版本不兼容。我正在嘗試使用寫在 ^0.7.6 上的合約從 ^0.4.x 合約中呼叫“safeTransferFrom(address,address,uint)”,即使我嘗試進行低級別呼叫,它也會導致還原。
0.4.x NFT 已經部署。我正在嘗試部署一個可以呼叫該契約的 0.7.6 契約。
這是我試圖與之互動的 0.4.x 合約的介面:
pragma solidity ^0.4.21; /** * @title ERC721 Non-Fungible Token Standard basic interface * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract ERC721Basic { function ownerOf(uint256 _tokenId) public view returns (address _owner); function exists(uint256 _tokenId) public view returns (bool _exists); function approve(address _to, uint256 _tokenId) public; function getApproved(uint256 _tokenId) public view returns (address _operator); function setApprovalForAll(address _operator, bool _approved) public; function isApprovedForAll(address _owner, address _operator) public view returns (bool); function transferFrom(address _from, address _to, uint256 _tokenId) public; function safeTransferFrom(address _from, address _to, uint256 _tokenId) public; }
以下是我想從我的 0.7.6 合約中呼叫的函式的重要部分:
function _executeOrder( address nftAddress, uint256 assetId, uint256 price, bytes memory fingerprint ) internal returns (Order memory) { ERC721BasicInterface nftRegistry = ERC721Interface(nftAddress); nftRegistry.safeTransferFrom(order.seller, _msgSender(), assetId); }
問題是,ERC721Interface應該在我的 0.7.6 契約中定義為什麼?很明顯,用 0.4.21 編寫的介面與 0.7.6(外部函式修飾符)不兼容。我嘗試在 0.4.21 NFT 上使用更現代的 ERC721 介面呼叫**safeTransferFrom ,但交易被還原。**這是我假設的正確行為,因為界面不同。
我懷疑這與 Solidity 版本無關。Solidity 中的
safeTransferFrom
功能keccak256("safeTransferFrom(address,address,uint256)")
對乙太坊虛擬機來說真的很重要。但是,我們不要迷失在細節上。當您呼叫
safeTransferFrom
時,該函式的呼叫者需要已通過該approve
函式獲得批准,如下所示:approve(futureCaller, tokenId)
. 完成後,您可以使用 確認誰獲准轉讓getApproved(tokenId)
。現在,當您
safeTransferFrom
從_executeOrder
自己的 0.7.6 合約中呼叫時,呼叫者就是您的 0.7.6 合約。所以你的合約需要得到代幣所有者的預先批准。所以解決方案是首先做(這裡的Javascript範例):
await the_0_4_Nft.methods .approve(my_0_7_6_contract_address, the_token_id) .send({ from: token_owner_address });
你可以簡單地用0.7.6版本寫一個介面。該介面並不關心目標合約是用什麼 Solidity 版本編譯的——它只是說明目標合約具有什麼功能。您基本上可以在任何您想要的版本中編寫介面(儘管最好使用明確支持介面的版本來編寫它)。
我只是更改了版本號並替換
public
為external
. 所以你的界面可能是這樣的:pragma solidity ^0.7.6; interface ERC721BasicInterface { function ownerOf(uint256 _tokenId) external view returns (address _owner); function exists(uint256 _tokenId) external view returns (bool _exists); function approve(address _to, uint256 _tokenId) external; function getApproved(uint256 _tokenId) external view returns (address _operator); function setApprovalForAll(address _operator, bool _approved) external; function isApprovedForAll(address _owner, address _operator) external view returns (bool); function transferFrom(address _from, address _to, uint256 _tokenId) external; function safeTransferFrom(address _from, address _to, uint256 _tokenId) external; }