Last active
February 15, 2024 16:45
-
-
Save BenFaruna/24f18fb4286b91abcf4b132e9f7a6d7a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.20; | |
interface IERC165 { | |
function supportsInterface(bytes4 interfaceID) external pure returns (bool); | |
} | |
interface IERC721 is IERC165 { | |
function balanceOf(address _owner) external view returns (uint _balance); | |
function ownerOf(uint _tokenId) external view returns (address _owner); | |
function safeTransferFrom(address _from, address _to, uint _tokenId) external payable; | |
function safeTransferFrom( | |
address _from, | |
address _to, | |
uint _tokenId, | |
bytes calldata _data | |
) external payable; | |
function transferFrom(address _from, address _to, uint _tokenId) external payable; | |
function approve(address _to, uint _tokenId) external; | |
function getApproved(uint _tokenId) external view returns (address _operator); | |
function setApprovalForAll(address _operator, bool _approved) external; | |
function isApprovedForAll( | |
address _owner, | |
address _operator | |
) external view returns (bool); | |
} | |
interface IERC721Receiver { | |
function onERC721Received( | |
address _operator, | |
address _from, | |
uint _tokenId, | |
bytes calldata _data | |
) external returns (bytes4); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.24; | |
import "./interface/IERC721.sol"; | |
contract ERC721 is IERC721 { | |
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 | |
); | |
mapping(uint => address) internal _ownerOf; | |
mapping(address => uint) internal _balanceOf; | |
mapping(uint => address) internal _approvals; | |
mapping(address => mapping(address => bool)) public isApprovedForAll; | |
function supportsInterface( | |
bytes4 interfaceID | |
) external pure returns (bool) { | |
return | |
interfaceID == type(IERC721).interfaceId || | |
interfaceID == type(IERC165).interfaceId; | |
} | |
function ownerOf(uint tokenId) external view returns (address) { | |
require( | |
_ownerOf[tokenId] != address(0), | |
"NftContract: owner query for nonexistent token" | |
); | |
return _ownerOf[tokenId]; | |
} | |
function balanceOf(address owner) external view returns (uint) { | |
require( | |
owner != address(0), | |
"NftContract: balance query for the zero address" | |
); | |
return _balanceOf[owner]; | |
} | |
function safeTransferFrom( | |
address _from, | |
address _to, | |
uint _tokenId | |
) external payable { | |
_transferFrom(_from, _to, _tokenId); | |
require( | |
_to.code.length == 0 || | |
IERC721Receiver(_to).onERC721Received( | |
msg.sender, | |
_from, | |
_tokenId, | |
"" | |
) == | |
bytes4( | |
keccak256("onERC721Received(address,address,uint256,bytes)") | |
), | |
"unsafe receiver" | |
); | |
} | |
function safeTransferFrom( | |
address _from, | |
address _to, | |
uint _tokenId, | |
bytes calldata _data | |
) external payable { | |
_transferFrom(_from, _to, _tokenId); | |
require( | |
_to.code.length == 0 || | |
IERC721Receiver(_to).onERC721Received( | |
msg.sender, | |
_from, | |
_tokenId, | |
_data | |
) == | |
bytes4( | |
keccak256("onERC721Received(address,address,uint256,bytes)") | |
), | |
"unsafe receiver" | |
); | |
} | |
function transferFrom( | |
address _from, | |
address _to, | |
uint _tokenId | |
) external payable { | |
_transferFrom(_from, _to, _tokenId); | |
} | |
function _transferFrom(address _from, address _to, uint _tokenId) internal { | |
require( | |
_from != address(0), | |
"NftContract: transfer from the zero address" | |
); | |
require(_to != address(0), "NftContract: transfer to the zero address"); | |
require( | |
_ownerOf[_tokenId] == _from, | |
"NftContract: transfer of token that is not owner" | |
); | |
require( | |
msg.sender == _from || | |
_approvals[_tokenId] == msg.sender || | |
isApprovedForAll[_from][msg.sender], | |
"NftContract: transfer caller is not owner nor approved" | |
); | |
_balanceOf[_from]--; | |
_balanceOf[_to]++; | |
_ownerOf[_tokenId] = _to; | |
delete _approvals[_tokenId]; | |
emit Transfer(_from, _to, _tokenId); | |
} | |
function approve(address _to, uint _tokenId) external { | |
address owner = _ownerOf[_tokenId]; | |
require( | |
msg.sender == owner || isApprovedForAll[owner][msg.sender], | |
"NftContract: approve caller is not owner" | |
); | |
_approvals[_tokenId] = _to; | |
} | |
function getApproved( | |
uint _tokenId | |
) external view returns (address _operator) { | |
require( | |
_ownerOf[_tokenId] != address(0), | |
"NftContract: approved query for nonexistent token" | |
); | |
return _approvals[_tokenId]; | |
} | |
function setApprovalForAll(address _operator, bool _approved) external { | |
require(_operator != msg.sender, "NftContract: approve to caller"); | |
require( | |
_operator != address(0), | |
"NftContract: approve to the zero address" | |
); | |
isApprovedForAll[msg.sender][_operator] = _approved; | |
emit ApprovalForAll(msg.sender, _operator, _approved); | |
} | |
function _mint(address to, uint id) internal { | |
require(to != address(0), "mint to zero address"); | |
require(_ownerOf[id] == address(0), "already minted"); | |
_balanceOf[to]++; | |
_ownerOf[id] = to; | |
emit Transfer(address(0), to, id); | |
} | |
function _burn(uint id) internal { | |
address owner = _ownerOf[id]; | |
require(owner != address(0), "not minted"); | |
_balanceOf[owner] -= 1; | |
delete _ownerOf[id]; | |
delete _approvals[id]; | |
emit Transfer(owner, address(0), id); | |
} | |
} | |
contract BfaNft is ERC721 { | |
function mint(address to, uint id) external { | |
_mint(to, id); | |
} | |
function burn(uint id) external { | |
require(msg.sender == _ownerOf[id], "not owner"); | |
_burn(id); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment