Applications that complete tasks through consensus mechanisms and blockchain platforms are inherently decentralized and do not rely on any centralized servers,promoting safer user transactions.
contract ERC721 is IERC721,IERC165{
mapping(bytes4=>bool)supportsInterfaces;
bytes4 invalidID=0xffffffff;
bytes4 constant ERC165_InterfaceID=0x01ffc9a7;//erc165
bytes4 constant ERC721_InterfaceID=0x80ac58cd;//erc721
mapping(address=>uint256)ercTokenCount;
mapping(uint256=>address)ercTokenOwner;
mapping(uint256=>address)ercTokenApproved;
mapping(address=>mapping(address=>bool))ercOperatorForAll;
using Address for address;
constructor(){
_registerInterface(ERC165_InterfaceID);
_registerInterface(ERC721_InterfaceID);
}
//授权
modifier canOperator(uint256 _tokenId){
address owner=ercTokenOwner[_tokenId];
require(msg.sender==owner||ercOperatorForAll[owner][msg.sender]);
_;
}
modifier canTransfer(uint256 _tokenId,address _from){
address owner=ercTokenOwner[_tokenId];
require(owner==_from);
require(msg.sender==owner||msg.sender==ercTokenApproved[_tokenId]||ercOperatorForAll[owner][msg.sender]);
_;
}
function _registerInterface(bytes4 interfaceID)internal{
supportsInterfaces[interfaceID]=true;
}
function supportsInterface(bytes4 interfaceID)override external view returns(bool){
require(invalidID!=interfaceID);
return supportsInterfaces[interfaceID];
}
//721
function balanceOf(address _owner)override external view returns(uint256){
return ercTokenCount[_owner];
}
function ownerOf(uint256 _tokenId)override external view returns(address){
return ercTokenOwner[_tokenId];
}
function getApproved(uint256 _tokenId)override external view returns(address){
return ercTokenApproved[_tokenId];
}
function isApprovedForAll(address _owner,address _operator)external view returns(bool){
return ercOperatorForAll[_owner][_operator];
}
function approve(address _approved,uint256 _tokenId)override external payable{
ercTokenApproved[_tokenId]=_approved;
emit Approval(msg.sender,_approved,_tokenId);
}
function setApprovalForAll(address _operator,bool _approved)override external{
ercOperatorForAll[msg.sender][_operator]=_approved;
emit ApprovalForAll(msg.sender,_operator,_approved);
}
function transferFrom(address _from,address _to,uint256 _tokenId)override external payable{
_transferFrom(_from,_to,_tokenId);
}
function _transferFrom(address _from,address _to,uint256 _tokenId)internal canTransfer(_tokenId,_from){
ercTokenOwner[_tokenId]=_to;
ercTokenCount[_to]+=1;
ercTokenApproved[_tokenId]=address(0);
emit Transfer(_from,_to,_tokenId);
}
function safeTransferFrom(address _from,address _to,uint256 _tokenId,bytes memory data)override external payable{
_safeTransferFrom(_from,_to,_tokenId,data);
}
function safeTransferFrom(address _from,address _to,uint256 _tokenId)override external payable{
_safeTransferFrom(_from,_to,_tokenId,"");
}
function _safeTransferFrom(address _from,address _to,uint256 _tokenId,bytes memory data)internal{
_transferFrom(_from,_to,_tokenId);
//add safe code
if(_to.isContract()){//首先判断对方是否是合约
bytes4 retval=ERC721TokenReceiver(_to).onERC721Received(msg.sender,_from,_tokenId,data);
require(retval==ERC721TokenReceiver.onERC721Received.selector);
}
}
function mint(address _to,uint256 _tokenId,bytes memory data)external{
require(_to!=address(0));
require(ercTokenOwner[_tokenId]==address(0));
ercTokenOwner[_tokenId]=_to;
ercTokenCount[_to]+=1;
if(_to.isContract()){//首先判断对方是否是合约
bytes4 retval=ERC721TokenReceiver(_to).onERC721Received(msg.sender,address(0),_tokenId,data);//是否实现了ERC721Received
require(retval==ERC721TokenReceiver.onERC721Received.selector);
}
emit Transfer(address(0),_to,_tokenId);
}