You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
// ERC20 contract interface
interface Token {
function balanceOf(address account) external view returns (uint256);
}
contract BalanceChecker {
/* Fallback function, don't accept any ETH */
receive() external payable {
revert("BalanceChecker does not accept payments");
}
/*
Check the token balance of a wallet in a token contract
Returns the balance of the token for user. Avoids possible errors:
- return 0 on non-contract address
- returns 0 if the contract doesn't implement balanceOf
*/
function tokenBalance(address user, address token) public view returns (uint256) {
// check if token is actually a contract
uint256 tokenCode;
assembly { tokenCode := extcodesize(token) } // contract code size
// is it a contract and does it implement balanceOf
if (tokenCode > 0) {
(bool success, bytes memory data) = token.staticcall(abi.encodeWithSignature("balanceOf(address)", user));
if (success) {
return abi.decode(data, (uint256));
}
}
return 0;
}
/*
Check the token balances of a wallet for multiple tokens.
Pass address(0) as a "token" address to get ETH balance.
Possible error throws:
- extremely large arrays for user and/or tokens (gas cost too high)
Returns a one-dimensional array that's user.length * tokens.length long. The
array is ordered by all of the 0th users token balances, then the 1st
user, and so on.
*/
function balances(address[] calldata users, address[] calldata tokens) external view returns (uint256[] memory) {
uint256[] memory addrBalances = new uint256[](tokens.length * users.length);
for (uint256 i = 0; i < users.length; i++) {
for (uint256 j = 0; j < tokens.length; j++) {
uint256 addrIdx = j + tokens.length * i;
if (tokens[j] != address(0)) {
addrBalances[addrIdx] = tokenBalance(users[i], tokens[j]);
} else {
addrBalances[addrIdx] = users[i].balance; // ETH balance
}
}
}
return addrBalances;
}
}
Here is also a javascript/typescript function that can be used to optimize the amount of call to the contract so the page never execed 100
import{BalanceChecker}from'balance-checker'// this is typechain generated by hardhat with the previous contracttypeAddress=stringtypeToken=stringinterfaceResult{address: Addresstoken: Tokenbalance: bigint}exportasyncfunctionbalanceCheckerProcessInBatches(addresses: Address[],tokens: Token[],balanceChecker: BalanceChecker,): Promise<Result[]>{constresults: Result[]=[]constmaxBatchSize=100for(leti=0;i<addresses.length;i++){for(letj=0;j<tokens.length;j+=maxBatchSize){// Create subsets of addresses and tokens while respecting the limit of 100constbatchTokens=tokens.slice(j,Math.min(j+maxBatchSize,tokens.length),)constcurrentBatchSize=batchTokens.lengthconstremainingCapacity=maxBatchSize-currentBatchSizeletbatchAddresses: Address[]=[addresses[i]]if(remainingCapacity>0&&i+1<addresses.length){constextraAddresses=Math.min(Math.floor(remainingCapacity/tokens.length),addresses.length-i-1,)batchAddresses=batchAddresses.concat(addresses.slice(i+1,i+1+extraAddresses),)i+=extraAddresses// Move forward the address index}constbalances=awaitbalanceChecker.balances(batchAddresses,batchTokens,)if(balances.length!==batchAddresses.length*batchTokens.length){thrownewError(`Batch mismatch: Expected ${batchAddresses.length*batchTokens.length} balances, but got ${balances.length}`,)}for(leta=0;a<batchAddresses.length;a++){for(lett=0;t<batchTokens.length;t++){results.push({address: batchAddresses[a],token: batchTokens[t],balance: balances[a*batchTokens.length+t],})}}}}returnresults}/** * Test code below */// const addresses = Array.from({ length: 50 }, (_, i) => `0xAddress${i + 1}`)// const tokens = Array.from({ length: 2 }, (_, i) => `Token${i + 1}`)//// const balanceChecker = {// balances: async (// addresses: Address[],// tokens: Token[],// ): Promise<bigint[]> => {// console.log(// `Page size: ${addresses.length * tokens.length} (address ${addresses.length}) (tokens ${tokens.length})`,// )//// const arrayOfBigInt = [];// for (let i = 0; i < addresses.length; i++) {// for (let j = 0; j < tokens.length; j++) {// arrayOfBigInt.push(BigInt(addresses[i].length + tokens[j].length));// }// }//// console.log(`Confirmed page size: ${arrayOfBigInt.length}`);// return arrayOfBigInt;// },// }//// ;(async () => {// const results = await balanceCheckerProcessInBatches(addresses, tokens, balanceChecker as BalanceChecker)//// results.forEach((result) => {// console.log(`Address: ${result.address}, Token: ${result.token}, Balance: ${result.balance}`);// })//// console.log(`Total number of results: ${results.length}`)// })()
The commented code is for testing yourself, in case you don't trust.
This is awesome however, I am struggling trying to pass 0x0 to get ETH balance, with your deployed version on mainnet, or with my hardhat fork.
I keep having such kind of errors: : RangeError: cannot slice beyond data bounds (buffer=0x, length=0, offset=4, code=BUFFER_OVERRUN, version=6.13.1)
When I deploy my own BalanceChecker.sol, I don´t get much more information:
eth_call
Contract call: <UnrecognizedContract>From: 0xbaa4dbc880eaf033fd6a01128116a060ca2ac661
To: 0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e
Error: Transactionrevertedwithoutareason
Any clue how to get ETH balance ?
The text was updated successfully, but these errors were encountered:
@kopax You're experiencing a python error. It sounds like your query would be best dealt with by the support team. I'll have to refer you to the official support live chat with the ticket ID TRT07638 Please see the link below to our dedicated support line: Trustwallet live support Click on the live chat icon at the bottom corner of the page to initiate chat with a live support agent.
@Clarevero1 , there is not a single line of python involved. Maybe you should get a real job and learn programming languages instead of scamming people.
Hello, first of all thanks for sharing.
I have updated the code for Solidity 0.8:
Here is also a javascript/typescript
function
that can be used to optimize the amount of call to the contract so the page never execed 100The commented code is for testing yourself, in case you don't trust.
This is awesome however, I am struggling trying to pass 0x0 to get ETH balance, with your deployed version on mainnet, or with my hardhat fork.
I keep having such kind of errors:
: RangeError: cannot slice beyond data bounds (buffer=0x, length=0, offset=4, code=BUFFER_OVERRUN, version=6.13.1)
When I deploy my own
BalanceChecker.sol
, I don´t get much more information:Any clue how to get ETH balance ?
The text was updated successfully, but these errors were encountered: