问题描述
我已经实施了一个基本合约,可以铸造代币、将代币转移到其他人的账户以及购买 NFT。这是在 Remix 上测试的完全实现的代码。
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import '@openzeppelin/contracts/utils/Counters.sol';
import '@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol';
contract ArtWorkMinter is ERC721URIStorage{
mapping(uint256 => address) idToOwner;
mapping(address => uint256[]) userTokenList;
mapping(uint256 => uint256) tokenPriceList;
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
constructor() ERC721("MyNFT","MNFT") {}
function mint_art_work(address receiver,string memory tokenURI,uint price) external {
_tokenIds.increment();
uint256 newNftTokenId = _tokenIds.current();
_mint(receiver,newNftTokenId);
_setTokenURI(newNftTokenId,tokenURI);
userTokenList[receiver].push(newNftTokenId);
idToOwner[newNftTokenId] = receiver;
tokenPriceList[newNftTokenId] = price;
}
function my_total_tokens(address receiver) external view returns (uint256){
return userTokenList[receiver].length;
}
function get_my_nft_tokens(address receiver) external view returns (uint256[] memory){
return userTokenList[receiver];
}
function get_token_details(uint token_id) external view returns (string memory){
return tokenURI(token_id);
}
function _transfer_token(address from_address,address to_address,uint token_id) internal{
// Update contract variables --
idToOwner[token_id] = to_address;
// Move the last element into the place of token id,delete the last item in array --
for(uint i = 0; i<userTokenList[from_address].length-1; i++){
if(userTokenList[from_address][i] == token_id){
userTokenList[from_address][i] = userTokenList[from_address][userTokenList[from_address].length - 1];
userTokenList[from_address].pop();
break;
}
}
// Add nft token to to address mapping array --
userTokenList[to_address].push(token_id);
}
function transfer_token(address from_address,uint token_id) external{
// Check if the caller is the owner of the token id --
require(ownerOf(token_id) == msg.sender,"NOT OWNER");
// approve the target address on which we are going to transfer the token
approve(to_address,token_id);
// transfer the token --
safeTransferFrom(from_address,to_address,token_id);
_transfer_token(from_address,token_id);
}
function buy_token(uint token_id) external payable{
require(msg.value >= tokenPriceList[token_id]);
// approve the target address on which we are going to transfer the token
approve(msg.sender,token_id);
// transfer the token --
address token_owner = ownerOf(token_id);
safeTransferFrom(token_owner,msg.sender,token_id);
_transfer_token(token_owner,token_id);
// send the ETH to the seller
payable(token_owner).transfer(msg.value);
}
}
合约可以成功铸造代币和转移代币。但是,每当我执行函数 buy_token 时,都会出现以下错误:
transact to ArtWorkMinter.buy_token errored: VM error: revert.
revert
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.
我想我理解错误以及问题出在哪里,在 NFT 令牌从所有者账户转移到支出者账户之前,必须先批准调用者用户(支出者)。因为代币是由所有者创建的,所有者不会购买他自己的代币,其他一些用户会这样做。但是其他用户 (Spender) 不能调用 transferFrom 或 approve 因为他不是令牌的所有者。 那么,我们如何解决这个问题呢?解决此问题的标准方法是什么?
经过一番研究,我知道应该有一个额外的合同,称为“运营商合同”,它将代表所有者批准和转让代币。
如何实施此运营商合同以及此合同如何与主要 NFT 合同合并?
任何建议或示例将不胜感激。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)