Solidity

將 erc721 代幣作為代幣所有者轉移到合約中

  • March 14, 2022

我正在嘗試制定一個契約,允許 erc721 令牌的所有者(來自不同的契約)將他們的 nft 發送到這個新契約。

例如:我有一個基本的 erc721 鑄幣合約:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "hardhat/console.sol";

contract NFT is ERC721, Ownable {
   using Counters for Counters.Counter;
   Counters.Counter private _nftIds;

   string public URI;

   mapping(uint256 => address) public _getNftOwnerId;
   mapping(address => mapping(uint256 => uint256)) public _usersNfts;
   uint256[] public _allNfts;
   constructor() ERC721 ("Creators Never Die Moodboards", "CND") {}

   function mint() public returns(uint256) {
       uint256 newNftId = _nftIds.current();
       _safeMint(msg.sender, newNftId);

       _getNftOwnerId[newNftId] = msg.sender;
       _usersNfts[msg.sender][newNftId] = newNftId;

       _allNfts.push(newNftId);
       _nftIds.increment();

       console.log("nft minted with id", newNftId);
       return newNftId;
   }



}

現在我有一個單獨的契約,我試圖允許msg.sender將他們擁有的 tokenId 發送到這個新契約。

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "hardhat/console.sol";

contract BulkTransfer {
   using Counters for Counters.Counter;
   Counters.Counter private _nftIds;


   constructor() {}

   function approveContract(address _contractAddress) external {
       ERC721 token = ERC721(_contractAddress);
       require(token.balanceOf(msg.sender) > 0, "Caller must own nft");
       token.setApprovalForAll(address(this), true);
   }

   function bulkTransfer(address _contractAddress, uint256 _tokenId) external {
       ERC721 token = ERC721(_contractAddress);


       require(token.balanceOf(msg.sender) > 0, "Caller must own nft");
       require(token.ownerOf(_tokenId) == msg.sender, "You must own the token");

       token.transferFrom(msg.sender, address(this), _tokenId);

   }





}

當我呼叫該bulkTransfer函式時,我不斷收到錯誤消息:"ERC721: transfer caller is not owner nor approved".

當我呼叫aproveContract函式時,我得到"ERC721: approve to caller"

我在 remix ide 中做這一切。

該行:

token.transferFrom(msg.sender, address(this), _tokenId);

要求 msg.sender 批准部署 BulkTransfer 的合約,以轉移 msg.sender 的代幣。沒有這樣的批准,因此結果為:“ERC721:轉接呼叫者不是所有者,也不是批准”。

關於“ERC721:approval to caller”看看你從OpenZeppelin呼叫 setApprovalForAl :

function setApprovalForAll(address operator, bool approved) public virtual override {
   _setApprovalForAll(_msgSender(), operator, approved);
}

function _setApprovalForAll(
   address owner,
   address operator,
   bool approved
) internal virtual {
   require(owner != operator, "ERC721: approve to caller");
   _operatorApprovals[owner][operator] = approved;
   emit ApprovalForAll(owner, operator, approved);
}

用於批准的 msg.sender 是契約,並且 adress(this) 也是契約,您違反了要求聲明

require(owner != operator, "ERC721: approve to caller");

一般來說,NFT 和代幣不是這樣工作的。

當您代幣轉移到地址(外部擁有的賬戶契約賬戶)時,您會更新控制該代幣的智能合約中的值。

查看您的程式碼,在bulkTransfer函式中,您嘗試將發件人擁有的代幣 (CND) 分配給BulkTransfer合約。

如果這是你想做的,你只需要呼叫transferCND 智能合約中的方法。

請注意,使用 OpenZeppelin 提供的標準實現,如果您代幣發送到由智能合約而非 EOA 控制的地址,您將永遠失去這些代幣。

相反,如果您希望使用者能夠將自己的代幣發送到多個地址,並且 CND 合約沒有實現批量傳輸功能,您可以編寫和部署智能合約來做到這一點。

使用這種聯繫人並不是很便宜,所以我仍然不明白你為什麼需要它,但這就是你需要做的。

bulkTransfer必須更改為至少獲得一個接收者參數和一個tokenIds 列表,然後您必須遍歷所有選定的 tokenIds,並且您必須檢查每個 tokenIds 的容差 ( getApproved) 並將其傳輸呼叫類似token.transferFrom(msg.sender, recipient, _tokenId).

並且在呼叫合約中的bulkTransfer方法之前,所有者必須向參數中指定地址的 CND 合約BulkTransfer發送大量的批准交易( ) ,否則整個方法將失敗,即使您失敗了 100 個批准。approve(address _approved, uint256 _tokenId)``BulkTransfer``_approved bulkTransfer

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