如何将 NFT 转移到另一个智能合约?

马库斯佩蒂

我正在尝试建立一个托管合同,该合同将存款作为 NFT 存入合同。我正在努力将 NFT 存入合约。

我从一个简单的 NFT 开始,该 NFT 被铸造到带有 id 的地址。

contract MyEpicNFT is ERC721URIStorage {
  // Magic given to us by OpenZeppelin to help us keep track of tokenIds.
  using Counters for Counters.Counter;
  Counters.Counter private _tokenIds;

  // We need to pass the name of our NFTs token and its symbol.
  constructor() ERC721 ("SquareNFT", "SQUARE") {
    console.log("This is my NFT contract. Woah!");
    console.log(address(this));
  }

  // A function our user will hit to get their NFT.
  function makeNft() public {
    uint256 newItemId = _tokenIds.current();

    _safeMint(msg.sender, newItemId);

    _setTokenURI(newItemId, "https://jsonkeeper.com/b/1LHH");
    console.log("An NFT w/ ID %s has been minted to %s", newItemId, msg.sender);


    _tokenIds.increment();
  }
}

在这种情况下,已将 ID 为 0 的 NFT 铸造到合约的 msg.sender:0xdD870fA1b7C4700F2BD7f44238821C26f7392148

我现在知道我需要批准 Escrow 合约才能被允许“使用”这个代币。为了在 MyEpicNft 合约上执行此操作,我使用 MyEpicNft 的合约地址和铸造的 NFT 的 ID 调用批准函数。

console.log:
 This is my NFT contract. Woah!
 0x5fc7Dc95b4Bb48dbC9894fCaE417482cb8A6A45a

在我的情况下,我使用 (0x5fc7Dc95b4Bb48dbC9894fCaE417482cb8A6A45a, 0) 调用批准 - 这似乎有效。现在我需要在 NftEscrow 合约中做的是存入 NFT。

我正在使用的批准功能来自 ERC721 库

approve(address to, uint256 tokenId)

有一个 depositNFT 函数接受 NFT 地址 - 在我们的例子中是 0x5fc7Dc95b4Bb48dbC9894fCaE417482cb8A6A45a 和 0。但是当我这样做时,我收到错误消息:

The transaction has been reverted to the initial state.
Reason provided by the contract: "ERC721: transfer caller is not owner nor approved".
Debug the transaction to get more information.


contract NftEscrow is IERC721Receiver {
    
    enum ProjectState {newEscrow, nftDeposited, cancelNFT, ethDeposited, canceledBeforeDelivery, deliveryInitiated, delivered}
    
    address payable public sellerAddress;
    address payable public buyerAddress;
    address public nftAddress;
    uint256 tokenID;
    bool buyerCancel = false;
    bool sellerCancel = false;
    ProjectState public projectState;

    receive() external payable {
    
     }

    constructor(){
        sellerAddress = payable(msg.sender);
        projectState = ProjectState.newEscrow;
    }
    
    function onERC721Received( address , address , uint256 , bytes calldata  ) public pure override returns (bytes4) {
        return this.onERC721Received.selector;
    }
    
    function depositNFT(address _NFTAddress, uint256 _TokenID) public onlySeller {
        nftAddress = _NFTAddress;
        tokenID = _TokenID;
        ERC721(nftAddress).safeTransferFrom(msg.sender, address(this), tokenID);
        projectState = ProjectState.nftDeposited;
    }

    function depositEth() public payable {
        buyerAddress = payable(msg.sender);
        projectState = ProjectState.ethDeposited;
    }

    function confirmDelivery()public payable  {
        ERC721(nftAddress).safeTransferFrom(address(this), buyerAddress, tokenID);
        sellerAddress.transfer(address(this).balance);
    }
    

    modifier onlySeller() {
        require(msg.sender == sellerAddress);
        _;
    }

} 
 

不知道我做错了什么并且被困了一天。为什么我不能将 NFT 存入智能合约?

削减

"ERC721: transfer caller is not owner nor approved"如果以下情况均不成立,您的托管合同将恢复:

  1. msg.sender是合同的所有者
  2. msg.sender为所有人批准
  3. msg.sender被所有者批准用于该令牌

在您的情况下,我们选择第 3 个选项。

我们需要检查的是

  1. 您真的批准了正确的地址吗?
  2. 批准功能恢复了吗?

当托管合约调用 NFT 合约时

ERC721(nftAddress).safeTransferFrom(msg.sender, address(this), tokenID);

从 NFT 合约的角度来看,msg.sender就是托管合约。所以问题出在你的批准过程中的 99%。请分享有关此的更多信息。

编辑:

我们试图使以下条件为真,其中spender是托管合同的地址

return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);

如果 getApproved 确实返回了合约地址,请尝试在您的 nft 合约中添加以下函数:

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual override returns (bool) {
        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
        address owner = ERC721.ownerOf(tokenId);
        console.log("spender %s", spender);
        console.log("getApproved %s", getApproved(tokenId);
        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
    }

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何将记录从一个表转移到另一个表?

将溢出的内容从一个div转移到另一个

我如何将一个承诺resolve()转移到另一个承诺

如何将Amazon S3存储桶转移到另一个帐户?

使用Bitbucket,如何将提交从一个分支转移到另一个分支?

Twilio,如何将正在进行的呼叫转移到另一个号码

如何将变量从NSNumberFormatter转移到另一个ViewController?

如何将提交从master转移到另一个分支?

如何将滚轮或滚动事件从一个元素转移到另一个元素?

如何将价值从js转移到另一个js

我如何将标签转移到另一个容器

如何将数据从回调转移到Django中的另一个视图?

在pyiron中,如何将一些工作转移到另一个项目?

如何将一个静态列表的项目转移到另一个

将帖子从一个博客转移到另一个博客?

将一个JLabel的价值转移到另一个

将收集对象从一个jsp转移到另一个

如何将ArrayList从另一个活动转移到另一个活动

如何将http标头转移到另一个页面?

将数据从一个$ state转移到另一个

如何将结构从一个克隆转移到另一个

将变量从一个功能转移到另一个功能

如何将“链接”转移到另一个组件?

无法将一个标题下的值转移到另一个

如何将数组的一半转移到另一个不同大小的数组?

如何使用 ERC721 将 NFT 从一个帐户转移到另一个帐户?

如何将 ArrayList 转移到另一个活动

如何将用户写入的值转移到另一个文件?

如何将图像的颜色转移到另一个图像?