403. 授權 - ERC721 (ep.25)

閱讀時間約 8 分鐘

1. 授權特定NFT給第三方管理 function approve(address to, uint256 tokenId) external;

  1. 呼叫者msg.sender授權編號為tokenId的NFT從持有者from轉移給接收者to
  2. 須要觸發Approval事件
  3. 特殊判斷:
  • to跟owner不能相同, 避免發生授權給持有者自己的情況
  • 若呼叫者沒有以下身份, 則撤回整筆交易
  • 呼叫者為持有者
  • 呼叫者被持有者授權管理全部的NFT (透過isApprovedForAll檢查)

2. 查詢特定NFT授權給誰 function getApproved(uint256 tokenId) returns (address );

  1. 給定一個Token ID(uint256), 回傳該NFT的被授權者 address
  2. 特殊檢查 - tokenId 必須是已經被鑄造且未被銷毀的NFT

3. 授權 / 撤銷全部的NFT管理權給第三方位址 function setApprovalforAll(address operator, bool _approved) external;

  1. 呼叫者msg.sender​授權或撤銷(以 _approved為準
  2. NFT管理第三方位址operator
  3. 須要觸發ApprovalForall事件
  4. 特殊判斷: operator與owner不能相同, 避免發生授權給持有者自己的情況。

4. 查詢授權/撤銷全部管理權限的情況 function isApprovedForAll(address owner, address operator) external view returns(bool);

  1. 給定持有者位址owner與欲查詢之第三方位址operator, 回傳是否授權


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

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);
}

contract ERC721 is IERC721 {
mapping(address => uint256) _balances;
mapping(uint256 => address) _owners;
mapping(uint256 => address) _tokenApprovals;
mapping(address => mapping(address => bool)) _operatorApprovals;

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];
}

}








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