Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new Solidity utility contract under packages/contracts to query ERC20 balances (single + batch) and also returns the native (ETH) balance in the batch variant.
Changes:
- Introduces
BalanceCheckercontract with a single-token balance getter. - Adds an overloaded batch balance getter that also appends native balance.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return IERC20(_token).balanceOf(_account); | ||
| } | ||
|
|
||
| function getTokenBalance(address[] memory _token, address _account) external view returns (uint256[] memory) { |
There was a problem hiding this comment.
These two overloaded getTokenBalance functions can be awkward for off-chain consumers (ethers/web3) because calling an overloaded function often requires using the fully-qualified signature string. If this contract is intended for broad external consumption, consider renaming the array version to something like getTokenBalances (and/or clarifying whether native balance is included).
| function getTokenBalance(address[] memory _token, address _account) external view returns (uint256[] memory) { | |
| function getTokenBalances(address[] memory _token, address _account) external view returns (uint256[] memory) { |
| function getTokenBalance(address _token, address _account) external view returns (uint256) { | ||
| return IERC20(_token).balanceOf(_account); | ||
| } | ||
|
|
||
| function getTokenBalance(address[] memory _token, address _account) external view returns (uint256[] memory) { |
There was a problem hiding this comment.
A new intent contract is introduced without corresponding unit tests. The packages/contracts/test/unit/intent/ suite has coverage for other intent contracts; adding tests for both the single-token and multi-token/native-balance behaviors would help prevent regressions and clarify the intended return shape.
| uint256[] memory balances = new uint256[](_token.length + 1); | ||
| for (uint256 i = 0; i < _token.length; i++) { | ||
| balances[i] = IERC20(_token[i]).balanceOf(_account); | ||
| } | ||
| balances[_token.length] = _account.balance; | ||
| return balances; | ||
| } |
There was a problem hiding this comment.
The array overload of getTokenBalance allocates tokens.length + 1 and appends the native (ETH) balance at the end. Given the function name/signature, this is easy for callers to misinterpret and can lead to off-by-one mistakes (output length no longer matches the input token list). Consider renaming and/or changing the API so the return shape clearly reflects whether native balance is included and in what position.
| uint256[] memory balances = new uint256[](_token.length + 1); | |
| for (uint256 i = 0; i < _token.length; i++) { | |
| balances[i] = IERC20(_token[i]).balanceOf(_account); | |
| } | |
| balances[_token.length] = _account.balance; | |
| return balances; | |
| } | |
| uint256[] memory balances = new uint256[](_token.length); | |
| for (uint256 i = 0; i < _token.length; i++) { | |
| balances[i] = IERC20(_token[i]).balanceOf(_account); | |
| } | |
| return balances; | |
| } | |
| function getNativeBalance(address _account) external view returns (uint256) { | |
| return _account.balance; | |
| } |
| return IERC20(_token).balanceOf(_account); | ||
| } | ||
|
|
||
| function getTokenBalance(address[] memory _token, address _account) external view returns (uint256[] memory) { |
There was a problem hiding this comment.
getTokenBalance(address[] ...) takes the token array as memory even though the function is external. Using calldata here avoids an unnecessary copy and is the common pattern used elsewhere in this package for external array inputs.
| function getTokenBalance(address[] memory _token, address _account) external view returns (uint256[] memory) { | |
| function getTokenBalance(address[] calldata _token, address _account) external view returns (uint256[] memory) { |
| import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; | ||
|
|
||
| contract BalanceChecker { | ||
| constructor() {} |
There was a problem hiding this comment.
Empty constructor is redundant here (no state initialization) and can be removed to reduce bytecode size and avoid implying there is construction logic.
| constructor() {} |
| // SPDX-License-Identifier: MIT | ||
| pragma solidity 0.8.25; | ||
|
|
||
| import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; |
There was a problem hiding this comment.
Import formatting is inconsistent with the rest of the Solidity codebase, which uses no spaces inside the curly braces (e.g. import {IERC20} ...). This file currently uses import { IERC20 } ...; consider matching the existing style to keep forge fmt / lint output consistent.
| import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; | |
| import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; |
🤖 Linear
Adding balance checker to the monorepo.