Solidity

如何使用solidity從錢包地址獲取相應的代幣地址

  • November 10, 2022
pragma solidity >=0.4.25 <0.9.0;

contract HelloBlockchain {
   struct token {
       address token;
       uint256 balance;
   }

   token[] res;

   function getBalances(address walletAddress, address[] memory tokenAddress) public returns(token[] memory){
       for (uint i = 0; i < tokenAddress.length; i++) {
       (bool success, bytes memory data) = address(tokenAddress[i]).call(abi.encodeWithSignature("balanceOf(address)", walletAddress));
           uint256 amount = abi.decode(data, (uint256));
           res.push(token(tokenAddress[i], amount));
       }
       return res;
   }
}

函式參數是一個錢包地址和一個代幣地址數組,該函式將遍歷代幣地址以查找該特定代幣的錢包餘額。但是,當我部署並執行該功能時,我一直遇到錯誤的交易被探勘但執行錯誤,我不確定這意味著什麼以及如何繼續

錯誤資訊

如果它們是您的契約的孩子或至少是導入的,您只能呼叫這樣的函式,所以是的,這一行是無效的

uint256 amt = tokenAddress[i].getBalances(walletAddress);

但我認為你走在正確的道路上;你可以使用這個呼叫另一個合約:

//externalContractAddress
address contractFoo = 0x12000notFakeAddress00012739
//parameters like tokenId, etc.
parameters = bar 
(bool,data) = address(contractFoo).call("functionSignature",parameters)

IE。我有一個操作員契約,其功能呼叫另一個契約來刻錄 NFT 代幣,如下所示:

function burn (address foo, uint256 id) external {
address contractFoo = 0x12000notFakeAddress00012739
   (bool burned,) = address(contractFoo).call(
       abi.encodeWithSignature("burn(address,uint256,uint256)", foo, id, 1)
   );
   require(burned, "Burn Failed");
}

只需將銷毀函式 singature ( "burn(address,uint256,uint256)") 替換為從另一個合約中獲取餘額的函式

_______新編輯

我對你的程式碼做了一些重構;但是我必須道歉,因為我還找到了另一個實際上比我自己的回答更好的答案原因是呼叫函式可能會觸發區塊鏈儲存更改,因此 EVM 不允許您將其用作視圖函式,因此呼叫這個函式會觸發一個消耗gas的交易,你可以通過閱讀這裡的文件來推斷

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.25 <0.9.0;

contract HelloBlockchain {
   struct token {
       address token;
       uint256 balance;
   }

   function getBalances(address walletAddress, address[] memory tokenAddress) public returns(token[] memory){
       //cant push or pull if the array is not in storage so i make a fixed size array with 
       //the max possible lenght
       token[] memory res = new token[](tokenAddress.length); 

       for (uint i = 0; i < tokenAddress.length; i++) {
       (bool success, bytes memory data) = address(tokenAddress[i]).call(abi.encodeWithSignature("balanceOf(address)", walletAddress));
       if (success) {
           uint256 amount = abi.decode(data, (uint256));
           res[i]= token(tokenAddress[i], amount);
           }
       }
       return res;
   }
}

有關更多詳細資訊,請查看關於地址成員的solidity 文件,其中詳細說明了這個地址是什麼。呼叫

如果目標是製作自己的代幣

您必須在某處聲明函式 getBalances。通常,我們將繼承集成到 ERC,在本例中為 ERC20。因此,所有平衡都保存在私有映射中。

如果目標是達到特定的令牌

正如 Carlos 所說,您必須使用其地址呼叫另一個合約。但是出於安全問題,如果被呼叫的智能合約不可信,我會建議避免使用 Call。而是使用介面,和/或檢查他們使用什麼介面以及他們尊重什麼標準。

如果您需要/想要使用 Call,那麼您必須考慮返回的參數:(bool 成功,字節記憶體數據),其中 data 是一個字節包,您將在其中獲得但不僅是從被呼叫函式返回的值。而且在這種情況下最好使用彙程式序。

如果目標是讓所有可能屬於錢包的代幣

那麼,就不可能了,因為錢包不保存任何資訊。餘額保存在合約中的鍵值上(如果它們尊重某些 ERC,則映射):addressWallet -> 金額。

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