代币标准--ERC721协议源码解析
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
interface IERC721 is IERC165 {
// 定义Transfer事件,在发生交易转移时触发。Solidity event在 EVM 的日志记录功能之上提供了一个抽象。应用程序可以通过以太坊客户端的 RPC 接口订阅和监听这些事件
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
// 定义Approval事件,在发生代币授权时触发该事件
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
// 记录owner全部token授权给 operate事件
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
// 记录
function balanceOf(address owner) external view returns (uint256 balance);
// 获取token的拥有者地址
function ownerOf(uint256 tokenId) external view returns (address owner);
// 转移token从from到to地址
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
// 转移token从from到to地址
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
// 转移token从from到to地址 被
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
// 将token授权给to地址
function approve(address to, uint256 tokenId) external;
// 授权全部token给operate地址
function setApprovalForAll(address operator, bool _approved) external;
// 获取token的授权者地址
function getApproved(uint256 tokenId) external view returns (address operator);
// 判断owner是否授权给operator
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// 代币名称
string private _name;
// 代币标志
string private _symbol;
// tokenId 和 拥有者地址的映射
mapping(uint256 => address) private _owners;
// 地址拥有的代币数量
mapping(address => uint256) private _balances;
// token 与 被授权的地址的映射
mapping(uint256 => address) private _tokenApprovals;
// 拥有者 和 操作者之间的授权映射
mapping(address => mapping(address => bool)) private _operatorApprovals;
// 构造函数 初始化 name_, symbol_
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
// 是否使用了 ERC721接口
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
// 获取owner地址代币数量
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: address zero is not a valid owner");
return _balances[owner];
}
// 获取代币拥有地址
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: invalid token ID");
return owner;
}
// 获取代币名称
function name() public view virtual override returns (string memory) {
return _name;
}
// 获取代币标识
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
// 获取tokenURI
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
// 检查token是否存在
_requireMinted(tokenId);
// 获取baseURI
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
// 获取baseURI
function _baseURI() internal view virtual returns (string memory) {
return "";
}
function approve(address to, uint256 tokenId) public virtual override {
// 获取token的owner地址
address owner = ERC721.ownerOf(tokenId);
// 检查 to 和 owner 不相等
require(to != owner, "ERC721: approval to current owner");
// 检查 合约调用者是owner 或者 合约调用者获得了owner的授权approve
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not token owner or approved for all"
);
// 授权
_approve(to, tokenId);
}
// 获取token的approve地址
function getApproved(uint256 tokenId) public view virtual override returns (address) {
// 检查token是否存在
_requireMinted(tokenId);
return _tokenApprovals[tokenId];
}
// 设置 给operator的授权情况
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
// 判断 owner是否授权给operate
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
//检查 合约调用者是否是token的拥有者或者被授权approve
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
// 转移token
_transfer(from, to, tokenId);
}
// 转移token
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
// 转移函数
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory data
) public virtual override {
//检查 合约调用者是否是token的拥有者或者被授权approve
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_safeTransfer(from, to, tokenId, data);
}
// 转移token
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory data
) internal virtual {
_transfer(from, to, tokenId);
// 检查合约地址是否实现ERC721Receiver
require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
}
// 判断token是否存在
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
// 判断是否是token的拥有者或者被授权approve
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
}
// 铸造token
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
// 铸造token
function _safeMint(
address to,
uint256 tokenId,
bytes memory data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
// 铸造token
function _mint(address to, uint256 tokenId) internal virtual {
// 检查to不为空地址
require(to != address(0), "ERC721: mint to the zero address");
// 检查token是否存在
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
// to地址余额+1
_balances[to] += 1;
// 添加映射
_owners[tokenId] = to;
// 触发 Transfer事件
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId);
}
// 销毁token
function _burn(uint256 tokenId) internal virtual {
// 获取token 拥有者地址
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// 删除token与授权者映射
delete _tokenApprovals[tokenId];
// owner账户余额-1
_balances[owner] -= 1;
// 删除token 与拥有者映射
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId);
}
// 转移token
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
// 检查token拥有者与 from地址是否一致
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
// 检查 to地址是否为空地址
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// 移除token授权
delete _tokenApprovals[tokenId];
// from地址token数量-1
_balances[from] -= 1;
// to地址token数量-1
_balances[to] += 1;
// 添加to与token的映射关系
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
// 将token授权给to
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
// 设置owner与operate的approve授权状态
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
// 检查owner地址和operate地址是否一致
require(owner != operator, "ERC721: approve to caller");
// 设置owner与operate授权状态
_operatorApprovals[owner][operator] = approved;
// 触发ApprovalForAll时间 记录信息
emit ApprovalForAll(owner, operator, approved);
}
// 判断是否token是否已经存在
function _requireMinted(uint256 tokenId) internal view virtual {
require(_exists(tokenId), "ERC721: invalid token ID");
}
// 检查地址,如果地址是账户,则返回true,是合约的话则会判断,该合约是否有引用IERC721Receiver这个接口
//作为EIP-721的要求,如果一个合约要接受EIP-721,其必须要实现onERC721Received方法,当用户调用safeTransferFrom时,会在转账结束时,调用to地址的onERC721Received方法,此时该方法的返回值应该为bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory data
) private returns (bool) {
// 是否是合约地址,
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), 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;
}
}
// 定义转移代币前的函数
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
// 定义转移代币后的函数
function _afterTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!