如何将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();
}
}

在本例中,已向合同的消息提交人铸造了一个NFT w/ID 0:0xdD870fA1b7C4700F2BD7f44238821C26f7392148

我现在知道我需要批准托管合同才能";花费";这个令牌。为了在MyEpicNft合同上做到这一点,我调用了approve函数,其中包含MyEpic恩ft的合同地址和生成的NFT的Id。

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

在我的情况下,我用(0x5fc7Dc95b4Bb48dbC9894fCaE417482cb8A6A45a,0(调用approve-这似乎有效。现在,我需要在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用于该令牌

在您的情况下,我们选择第三种选择。

我们需要检查的是

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

相关内容

  • 没有找到相关文章

最新更新