407. 元資料 - ERC721 (ep.28)

閱讀時間約 21 分鐘

1. 名稱 function name() external view returns (string memory)

  • 回傳本合約的名字

2. 查詢NFT的URI function tokenURI(uint256 tokenId) external view returns (string memory);

  1. URI = Uniform Resource Identifier
  2. mapping(uint256 => string) _tokenURIs;
  3. 若資料會佔用不小空間, 則會用一個外部連結取代
  4. 用來指向一個在ipfs/http 上面的URI.json
  5. 該URI會儲存該NFT的資訊, 包含但不限於
  • 描述(description)
  • 外部連結(external_url)
  • 圖片網址(image):通常是ipfs/http, 有些簡單的也會直接用SVG以base64格式的文字
  • 動畫網址(animation_url)
  • 名稱(name)
  • 該NFT的屬性(attributes)

3. Opensea NFT

  1. Regenesis: Open Edition
  2. go to details - contract Address
  3. go to contract - read contract
  1. insert "0" in the coloum 11. tokenURI, then you can see the website of ipfs
  1. simple ipfs browser: paste in the link to check the NFT picture

ipfs://Qma3dgNvmqabeVchAfG95KyESXCDojo4b1Fc8U5xiZ89hf


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}

interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

interface IERC721Metadata {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}

interface IERC721{
// Event
event Transfer(address indexed from, address indexed to, uint256 tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

//Query
function balanceOf(address account) external view returns(uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);

//Transfer
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function transferFrom(address from, address to, uint256 tokenId) external;

// Approve
function approve(address to, uint256 tokenId) external;
function setApprovalforAll(address operator, bool _approved) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function isApprovedForAll(address owner, address operator) external view returns(bool);
// Mint
function mint(address to, uint256 tokenId) external;
function safemint(address to, uint256 tokenId, bytes memory data) external;
function safemint(address to, uint256 tokenId) external;
// Burn
function burn(uint256 tokenId) external;
}

contract ERC721 is IERC721, IERC721Metadata {
mapping(address => uint256) _balances;
mapping(uint256 => address) _owners;
mapping(uint256 => address) _tokenApprovals;
mapping(address => mapping(address => bool)) _operatorApprovals;
string _name;
string _symbol;
mapping(uint256 => string) _tokenURIs;
constructor(string memory name_, string memory symbol_){
_name = name_;
_symbol = symbol_;
}

function name() public view returns (string memory){
return _name;
}
function symbol() public view returns (string memory){
return _symbol;
}

function tokenURI(uint256 tokenId) public view returns (string memory) {
address owner = _owners[tokenId];
require(owner != address(0), "ERROR: token id is not valid");
return _tokenURIs[tokenId];
}

function setTokenURI(uint256 tokenId, string memory URI) public {
address owner = _owners[tokenId];
require(owner != address(0), "ERROR: token id is not valid");
_tokenURIs[tokenId] = URI;
}

function supportsInterface(bytes4 interfaceId) public pure returns (bool) {
return interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
interfaceId == type(IERC165).interfaceId;
}

function balanceOf(address owner) public view returns(uint256){
require(owner != address(0), "ERROR: address 0 cannot be owner");
return _balances[owner];
}

function ownerOf(uint256 tokenId) public view returns (address){
address owner = _owners[tokenId];
require(owner != address(0), "ERROR: tokenId is not valid Id");
return owner;
}

function approve(address to, uint256 tokenId) public {
address owner = _owners[tokenId];
require(owner != to,"ERROR: owner == to");
require(owner == msg.sender || isApprovedForAll(owner, msg.sender), "Error: Caller is not token owner / approved for all");
_tokenApprovals[tokenId] = to;
emit Approval(owner, to, tokenId);
}

function getApproved(uint256 tokenId) public view returns (address){
address owner = _owners[tokenId];
require(owner != address(0), "ERROR: Token is not minted or is burn");
return _tokenApprovals[tokenId];
}

function setApprovalforAll(address operator, bool _approved) public {
require(msg.sender != operator, "ERROR: 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 {
_transfer(from, to, tokenId);
}

function _transfer(address from, address to, uint256 tokenId) internal {
address owner = _owners[tokenId];
require(owner == from, "ERROR: Owner is not the from address");
require(msg.sender == owner || isApprovedForAll(owner, msg.sender) || getApproved(tokenId) == msg.sender, "ERROR: Caller doesn't have permission to transfer");
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 {
_safeTransfer(from, to, tokenId, data);
}

function safeTransferFrom(address from, address to, uint256 tokenId) public {
_safeTransfer(from, to, tokenId, "");
}

function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, data), "ERROR: ERCReceiver is not implemented");
}

function mint(address to, uint256 tokenId) public {
require(to != address(0), "ERROR: Mint to address 0");
address owner = _owners[tokenId];
require(owner == address(0), "ERROR: tokenId existed");
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
}

function safemint(address to, uint256 tokenId, bytes memory data) public {
mint(to, tokenId);
require(_checkOnERC721Received(address(0), to, tokenId, data), "ERROR: ERCReceiver is not implemented");
}

function safemint(address to, uint256 tokenId) public {
safemint(to, tokenId, "");
}

function burn(uint256 tokenId) public {
address owner = _owners[tokenId];
require(msg.sender == owner, "ERROR: only owner can burn");
_balances[_owners[tokenId]] -= 1;
delete _owners[tokenId];
delete _tokenApprovals[tokenId];
emit Transfer(owner, address(0), tokenId);
}

function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private returns (bool) {
if (to.code.length > 0 /* to is a contract*/) {
try IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
}







尋大神腳印, 亦步亦趨。
留言0
查看全部
發表第一個留言支持創作者!
從 Google News 追蹤更多 vocus 的最新精選內容