NFT 不連續性?
我對區塊鏈相當陌生。我對 ERC-721 NFT 的理解是它應該在地址之間以原子方式傳遞。特別是,如果我跟踪 NFT 的“from”和“to”欄位,並查看跨時間的交易,我應該會看到如下內容:
from -> to ========== A -> B B -> C C -> D
在檢查各種 ERC-721 令牌時,我發現這通常是正確的,但並非總是如此。例如,這個 NFT 似乎從一個錢包“傳送”到另一個:
https://etherscan.io/nft/0x11bCfAe88954f2961389658f5e57bE3B4d83D03E/10074
前面的案例只是一個例子;我可以提供更多。誰能幫我理解發生了什麼(或者我持有什麼錯誤的假設)?
NFTs是數字資產,你可以將它們轉移給其他人(個人錢包或智能合約)。首先NFTs鑄幣給代幣創建者(所有者),然後他們可以轉移到任何地方進行存款,出售或其他交易。根據您的連結,第一筆和最後一筆交易表明,為了更好地了解和跟踪此令牌的路線,您可以查看此連結。
是的,很難用幾行來解釋,但要理解轉移工作流程,
ERC-721
標準是基於可替代令牌標準ERC-20
的,因此它們都提供以下功能:將代幣從一個賬戶轉移到另一個賬戶,獲取一個賬戶的目前代幣數量,並批准第三方賬戶是否可以轉移代幣。
此外,ERC-721 代幣還提供以下 NFT 獨有的功能:
獲取特定令牌的所有者
那麼可以說 ERC-20 和 ERC-721 有兩個工作流程將代幣從一個地址轉移到另一個地址。第一個工作流在所有者轉移代幣時使用,它在
_transfer()
內部函式中實現如下:/** * Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _balances[from] -= 1; _balances[to] += 1; _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId); }
當第三方代表所有者使用該功能轉移代幣時,使用第二個轉移代幣的工作流程。
transferFrom()
function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _transfer(from, to, tokenId); }
換句話說,該
transferFrom()
函式正在檢查以下任何條件是否為真:
- msg.sender (呼叫此函式的人)是所有者。
- msg.sender已被批准代表所有者轉移令牌**。**
- 所有者已批准msg.sender轉移其所有代幣。
當所有者呼叫 transferFrom() 函式時,第一個條件為“真” **。**這意味著我們可以在上一節中看到的傳輸工作流程中使用 transferFrom() 函式。
該
getApproved()
函式用於第二個條件,它只是查找_tokenApprovals
私有變數。function getApproved(uint256 tokenId) public view virtual override returns (address) { require(_exists(tokenId), "ERC721: approved query for nonexistent token"); return _tokenApprovals[tokenId]; }
該
_tokenApprovals
變數是令牌 ID和address
.// Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals;
因此,所有者需要首先呼叫該
approve()
函式才能使第二個條件為真。它將花費者地址和令牌 ID 添加到_tokenApprovals
變數中,因此_isApprovedOrOwner()
內部函式將返回 true。在第三個條件中,該
isApprovedForAll()
函式檢查所有者是否已給予msg.sender全面批准以發送其代幣。function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; }