Solidity

在 Solidity 中列出所有使用者令牌的最佳方式

  • October 28, 2021

我正在使用 openzeppelin erc721 庫來創建 NFT,並且需要列出使用者的所有令牌。最明顯的方法是遍歷合約中的所有代幣,並檢查代幣的所有者是否與我發送的地址相同。

function tokensOfOwner(address _owner) external view returns(uint256[] ownerTokens) {
   uint256 tokenCount = balanceOf(_owner);

   if (tokenCount == 0) {
       // Return an empty array
       return new uint256[](0);
   } else {
       uint256[] memory result = new uint256[](tokenCount);
       uint256 totalCats = totalSupply();
       uint256 resultIndex = 0;

       // We count on the fact that all cats have IDs starting at 1 and increasing
       // sequentially up to the totalCat count.
       uint256 catId;

       for (catId = 1; catId <= totalCats; catId++) {
           if (kittyIndexToOwner[catId] == _owner) {
               result[resultIndex] = catId;
               resultIndex++;
           }
       }

       return result;
   }
}

連結到此解決方案

我正在考慮實施的另一個解決方案是有一個映射,我將使用者地址映射到一個數組或另一個包含使用者擁有的所有令牌的映射。將代幣轉移到另一個地址後,我需要從賣家列表中刪除代幣並將其添加到買家列表中。這個解決方案聽起來更合理,但我不知道它的成本效益如何。這種方法有什麼缺點?

這可以通過以下方式實現:

在合約級別聲明儲存變數

mapping(address => uint256[]) public userOwnedTokens;
mapping(uint256 => int256) public tokenIsAtIndex;

mint(tokenId) {
   // Prior minting logic from OpenZeppelin
   userOwnedTokens[msg.sender].push(tokenId);
   uint256 arrayLength = userOwnedTokens[msg.sender].length;
   tokenIsAtIndex[tokenId] = arrayLength;
}

要在沒有循環的情況下獲取所有使用者令牌,您所要做的就是,這是可能的,因為 userOwnedTokens 的訪問說明符是公共的

contractInstance.methods.userOwnedTokens.call(address) // THIS WILL RETURN AN ARRAY OF TOKEN IDs

在轉移代幣的情況下,更改 tokenIsAtIndex

$$ tokenId $$到 -1

transfer(from, to, tokenId) {
   // Transfer logic
   uint256 tokenIndex = tokenIsAtIndex[tokenId];
   userOwnedTokens[from][tokenIndex] = 000; // TO DENOTE THAT THE TOKEN HAS BEEN TRANSFERRED, YOU CAN USE ANY OTHER NUMBER
}

下次userOwnedTokens呼叫時,您可以檢查 tokenId 為 000 的任何地方,這些令牌已經轉移,您可以決定不在前端向使用者顯示它。

我希望它有幫助!!!!

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