Solidity

如何與任何 ERC721 合約互動?

  • March 23, 2022

我們可以與我們擁有樣本的合約進行互動。為了清楚起見,請參閱此響應中的契約如何Proxy與契約互動。Name

在我的場景中,我想檢查是否msg.sender是 NFT 的所有者。因此,我嘗試使用相同的方式與任何 ERC721 合約進行互動,而不是直接呼叫合約。像這樣:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "@openzeppelin/contracts@4.5.0/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts@4.5.0/token/ERC721/IERC721.sol";

contract Market {
   function putOnSale(address _nftContract, uint256 _tokenId, uint256 _price) public payable {
       address tokenOwner = ERC721(_nftContract).ownerOf(_tokenId); // ???
       require(tokenOwner == msg.sender, 'Only owner...');
       
       // Rest of the code...
   }
}

但是,當我呼叫putOnSale方法時出現此錯誤:

transact to Market.putOnSale errored: VM error: revert.

revert 
   The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance. Debug the transaction to get more information.

我不能用這種方式與另一個 ERC721 合約互動嗎?

注意:我在 Remix IDE JavaScript VM 中完成這一切。

提前致謝!

在您提供的很少內容中,我唯一能看到的是您正在使用應該使用界面的契約。即這一行:

  address tokenOwner = ERC721(_nftContract).ownerOf(_tokenId); // ???

應該:

   address tokenOwner = IERC721(_nftContract).ownerOf(_tokenId)

如果您不是來自習慣於使用指針的語言,那麼這兩者之間的區別可能會非常令人困惑。簡而言之,您使用:

  • 當你想要呼叫一個已經部署的合約時的介面( )。IERC721
  • 您要部署新合約時的合約****( ) ERC721

您現在所寫的內容看起來就像您正在嘗試部署一個新ERC721合約,_nftContract名稱為 ,然後立即詢問給定令牌的所有者。這裡的問題是,根據OpenZepplin 的 ERC721 API 文件,這種方法需要tokenId存在。由於此時您還沒有鑄造任何代幣,這將恢復交易。

如果您還是 Solidity 的新手並且對這些事情並不完全確定,我建議避免任何將程式碼減少到一個襯裡的初始誘惑。您會發現,有時VM error: revert您會從 EVM 錯誤消息中獲得更多洞察力。如果您有多個線上函式呼叫,這可能更難考慮。

把它寫成:

   IERC721 nft = IERC721(_nftContract);
   address tokenOwner = nft.ownerOf(_tokenId);

或者在部署新合約時,像這樣:

   ERC721 nft = new ERC721(_nftName, _nftSymbol);
   nft.mint(msg.sender, _tokenId);

可以更容易準確地知道哪裡出了問題,特別是因為您可能不知道通過的地址是否實際上是ERC721.

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