//实际上,去掉数量value才是erC721
//ERC721是藏品单份的NFT合约,ERC1155是藏品多份的NFT合约
//一般来说,ERC1155可以兼容ERC721的情况
interface IERC721Received {
function onERC721Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
}
function _doSafeTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) private {
if (to.code.length>0) {
try IERC721Received(to).onERC721Received(operator, from, id, amount, data) returns (bytes4 response) {
if (response != IERC721Received.onERC721Received.selector) {
revert("ERC721: onERC721Received rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC721: transfer to non ERC721Receiver implementer");
}
}
}
完整简化ERC721的代码:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
interface IERC721{
//Event
event Transfer(address indexed from,address indexed to,uint256 indexed tokenId);
event Approval(address indexed owner,address indexed approved,uint256 indexed tokenId);
event ApprovalForAll(address indexed owner,address indexed operator,bool approved);
//Query
//查询该拥有者持有的NFT数量
function balanceOf(address owner) external view returns(uint256 balance);
//查询该NFT的持有者
function ownerOf(uint256 tokenId) external view returns(address owner);
//Transfer
//转移NFT安全版本
function safeTransferFrom(address from, address to,uint256 tokenId,bytes calldata data)external;
function safeTransferFrom(address from, address to,uint256 tokenId)external;
//转移NFT
function transferFrom(address from,address to,uint256 tokenId) external;
//Approve
//授权特定NFT给第三方管理
function approve(address to,uint256 tokenId) external;
//授权或撤销第三方的管理权
function setApprovalForAll(address operator,bool _approved) external;
//查询该NFT的被授权者
function getApproved(uint256 tokenId)external view returns(address operator);
//查询第三方的管理权限
function isApprovedForAll(address owner,address operator) external view returns(bool);
}
interface IERC721Received {
function onERC721Received(
address operator,
address from,
uint256 id,
bytes calldata data
) external returns (bytes4);
}
contract ERC721 is IERC721{
address public _owner;//合约持有者
mapping(address => uint256) _balances;
mapping(uint256 => address) _owners;
mapping(uint256=>address) _tokenApprovals;
mapping(address=>mapping(address=>bool)) _operatorApprovals;
constructor(){
_owner=msg.sender;
}
function balanceOf(address owner) public view returns(uint256 balance){
require(owner!=address(0),"address 0 cannot be owner!");
return _balances[owner];
}
function ownerOf(uint256 tokenId) public view returns(address owner){
address ownerTemp = _owners[tokenId];
require(ownerTemp!=address(0),"tokenId is not vaild Id!");
return ownerTemp;
}
function approve(address to,uint256 tokenId) public{
address owner=_owners[tokenId];
require(owner!=to,"owner==to!");
require(owner==msg.sender||isApprovedForAll(owner,msg.sender),"no approve!");
_tokenApprovals[tokenId]=to;
emit Approval(owner,to,tokenId);
}
function getApproved(uint256 tokenId)public view returns(address operator){
address owner=_owners[tokenId];
require(owner!=address(0),"tokenId is not vaild Id!");
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator,bool _approved)public {
require(msg.sender!=operator,"owner==operator");
_operatorApprovals[msg.sender][operator]=_approved;
emit ApprovalForAll(msg.sender,operator,_approved);
}
function isApprovedForAll(address owner,address operator) public view returns(bool){
return _operatorApprovals[owner][operator];
}
function transferFrom(address from,address to,uint256 tokenId) public{
_transferFrom(from,to,tokenId);
}
function _transferFrom(address from,address to,uint256 tokenId) private{
address owner=_owners[tokenId];
require(msg.sender==owner||getApproved(tokenId)==owner||isApprovedForAll(owner,msg.sender),"no right!");
require(owner==from,"ownner is not the from address");
delete _tokenApprovals[tokenId];
_balances[from]-=1;
_balances[to]+1;
_owners[tokenId]=to;
emit Transfer(from,to,tokenId);
}
function safeTransferFrom(address from, address to,uint256 tokenId,bytes calldata data) public{
_transferFrom(from,to,tokenId);
_doSafeTransferAcceptanceCheck(msg.sender,from,to,tokenId,data);
}
function safeTransferFrom(address from, address to,uint256 tokenId)public{
_transferFrom(from,to,tokenId);
_doSafeTransferAcceptanceCheck(msg.sender,from,to,tokenId,"");
}
function _doSafeTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256 id,
bytes memory data
) private {
if (to.code.length>0) {
try IERC721Received(to).onERC721Received(operator, from, id, data) returns (bytes4 response) {
if (response != IERC721Received.onERC721Received.selector) {
revert("ERC721: onERC721Received rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC721: transfer to non ERC721Receiver implementer");
}
}
}
}