Skip to content

Instantly share code, notes, and snippets.

@KcPele
Created August 16, 2023 07:11
Show Gist options
  • Save KcPele/14444919b3d7a8b706f3eb8c5ef1b217 to your computer and use it in GitHub Desktop.
Save KcPele/14444919b3d7a8b706f3eb8c5ef1b217 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.8.18+commit.87f61d96.js&optimize=false&runs=200&gist=
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/// @title ERC-721 Non-Fungible Token Standard
/// @dev See https://eips.ethereum.org/EIPS/eip-721
/// Note: the ERC-165 identifier for this interface is 0x80ac58cd.
interface ERC721 /* is ERC165 */ {
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);
function balanceOf(address _owner) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
function setApprovalForAll(address _operator, bool _approved) external;
function approve(address _approved, uint256 _tokenId) external payable;
function getApproved(uint256 _tokenId) external view returns (address);
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable;
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
}
error ERC721Contract__AddressCannotBeZero();
error ERC721Contract__TokenIdDoesNotExist();
error ERC721Contract__MsgSenderIsNotTheOwner();
error ERC721Contract__FromAddressISNotTheOwner();
error ERC721Contract__ReceiverNotImplemented();
contract ERC721Contract is ERC721 {
mapping(address => uint256) internal _balances;
mapping(uint256 => address) internal _owners;
mapping(address => mapping(address => bool)) private _operatorApprovals;
mapping(uint256 => address ) private _tokenApprovals;
modifier checkTokenExist (uint256 _tokenId) {
if(_owners[_tokenId] == address(0)){
revert ERC721Contract__TokenIdDoesNotExist();
}
_;
}
function balanceOf(address _owner) public view returns(uint256) {
if(_owner == address(0)){
revert ERC721Contract__AddressCannotBeZero();
}
return _balances[_owner];
}
function ownerOf(uint256 _tokenId) public view checkTokenExist(_tokenId) returns(address){
address owner = _owners[_tokenId];
return owner;
}
function setApprovalForAll(address _operator, bool _approved) public {
_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 approve(address _to, uint256 _tokenId) public payable {
address owner = ownerOf(_tokenId);
if(msg.sender != owner || !isApprovedForAll(owner, msg.sender)){
revert ERC721Contract__MsgSenderIsNotTheOwner();
}
_tokenApprovals[_tokenId] = _to;
emit Approval(owner, _to, _tokenId);
}
function getApproved(uint256 _tokenId) public view checkTokenExist(_tokenId) returns(address){
return _tokenApprovals[_tokenId];
}
function transferFrom(address _from, address _to, uint256 _tokenId) public checkTokenExist(_tokenId) payable {
address owner = ownerOf(_tokenId);
if(_to != address(0)){
revert ERC721Contract__AddressCannotBeZero();
}
if(msg.sender != owner || !isApprovedForAll(owner, msg.sender) || getApproved(_tokenId) != msg.sender){
revert ERC721Contract__MsgSenderIsNotTheOwner();
}
if(owner != _from){
revert ERC721Contract__FromAddressISNotTheOwner();
}
approve(address(0), _tokenId);
_balances[_from] -= 1;
_balances[_to] += 1;
_owners[_tokenId] = _to;
emit Transfer(_from, _to, _tokenId);
}
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory _data) public payable {
transferFrom(_from, _to, _tokenId);
if(!_checkOnERC721Received()){
revert ERC721Contract__ReceiverNotImplemented();
}
}
function safeTransferFrom(address _from, address _to, uint256 _tokenId) public payable {
safeTransferFrom(_from, _to, _tokenId, "");
}
function _checkOnERC721Received() private pure returns(bool) {
return true;
}
function supportsInterface(bytes4 interfaceId) public pure virtual returns(bool) {
return interfaceId == 0x80ac58cd;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "./ERC721Contract.sol";
error SuperMarioWorld__TokenIdDoesNotExist();
contract SuperMarioWorld is ERC721Contract {
string private _name;
string private _symbol;
uint256 private _tokenCount;
mapping(uint256 => string) private _tokenURIs;
constructor(string memory name, string memory symbol) {
_name = name;
_symbol = symbol;
}
function tokenURL(uint256 _tokenId) external view returns(string memory) {
if(_owners[_tokenId] == address(0)) {
revert SuperMarioWorld__TokenIdDoesNotExist();
}
return _tokenURIs[_tokenId];
}
function mint(string memory _tokenURI) external {
_tokenCount += 1;
_balances[msg.sender] += 1;
_owners[_tokenCount] = msg.sender;
_tokenURIs[_tokenCount] = _tokenURI;
emit Transfer(address(0), msg.sender, _tokenCount);
}
function supportsInterface(bytes4 _interfaceId) public pure override returns(bool) {
return _interfaceId == 0x80ac58cd || _interfaceId == 0x5b5e139f;
}
function getName() external view returns(string memory) {
return _name;
}
function getSymbol() external view returns(string memory){
return _symbol;
}
function getTokenCount() external view returns(uint256) {
return _tokenCount;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment