Erc-721

您如何與 ^0.7.6 合約中的 ^0.4.x ERC721 互動?

  • October 5, 2021

在我看來,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 版本編譯的——它只是說明目標合約具有什麼功能。您基本上可以在任何您想要的版本中編寫介面(儘管最好使用明確支持介面的版本來編寫它)。

我只是更改了版本號並替換publicexternal. 所以你的界面可能是這樣的:

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;
}

引用自:https://ethereum.stackexchange.com/questions/111035