Transactions

NFT 不連續性?

  • November 7, 2022

我對區塊鏈相當陌生。我對 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變數是令牌 IDaddress.

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

引用自:https://ethereum.stackexchange.com/questions/138936