// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "@openzeppelin/contracts/utils/Address.sol"; contract BlChNFT is IERC721, IERC721Metadata { using Strings for uint256; using Address for address; mapping(address => uint256) private _balances; mapping(uint256 => address) private _owners; mapping(uint256 => address) private _tokenApprovals; mapping(address => mapping(address => bool)) private _operatorApprovals; address private ownerNFT; constructor() { ownerNFT = msg.sender; } function _mint(address to, uint256 tokenId) external { require(ownerNFT == msg.sender, "only onwner"); require(_owners[tokenId] == address(0), "ERC721: token already minted"); _balances[to] += 1; _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); } function name() external pure returns (string memory){return "Blockchain NFT";} function symbol() external pure returns (string memory){return "BlChNFT";} function tokenURI(uint256 _tokenId) external pure returns (string memory){ return string(abi.encodePacked("https://dsl.hsr.ch/nft/", _tokenId.toString())); } function supportsInterface(bytes4 interfaceId) external pure returns (bool){ return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || interfaceId == type(IERC165).interfaceId; } function balanceOf(address _owner) external view returns (uint256) { return _balances[_owner]; } function ownerOf(uint256 _tokenId) public view returns (address) { return _owners[_tokenId]; } function getApproved(uint256 _tokenId) public view returns (address){ return _tokenApprovals[_tokenId]; } function isApprovedForAll(address _owner, address _operator) public view returns (bool){ return _operatorApprovals[_owner][_operator]; } function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory _data) public override { transferFrom(_from, _to, _tokenId); if (_to.isContract()) { bytes4 retVal = IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data); require (retVal == IERC721Receiver.onERC721Received.selector, "ERC721: transfer to non ERC721Receiver implementer"); } } function safeTransferFrom(address _from, address _to, uint256 _tokenId) external override { safeTransferFrom(_from, _to, _tokenId, ""); } function transferFrom(address _from, address _to, uint256 _tokenId) public override{ address owner = ownerOf(_tokenId); require(msg.sender == owner || getApproved(_tokenId) == msg.sender || isApprovedForAll(owner, msg.sender), "ERC721: safeTransferFrom caller is not owner nor approved for all"); // Clear approvals from the previous owner _tokenApprovals[_tokenId] = address(0); emit Approval(owner, address(0), _tokenId); _balances[_from] -= 1; _balances[_to] += 1; _owners[_tokenId] = _to; emit Transfer(_from, _to, _tokenId); } function approve(address _to, uint256 _tokenId) external override{ address owner = ownerOf(_tokenId); require(msg.sender == owner || isApprovedForAll(owner, msg.sender), "ERC721: approve caller is not owner nor approved for all"); _tokenApprovals[_tokenId] = _to; emit Approval(owner, _to, _tokenId); } function setApprovalForAll(address _operator, bool _approved) external{ _operatorApprovals[msg.sender][_operator] = _approved; emit ApprovalForAll(msg.sender, _operator, _approved); } }