技术问询:Uniswap如何获取ETH或ERC20代币余额?
Uniswap中ETH/ERC20余额查询的实现方式
Uniswap并没有专门开发余额查询的合约逻辑,它是借助Multicall合约批量调用标准查询方法来获取地址的ETH或ERC20代币余额,这也是DeFi领域批量数据查询的通用方案。
1. ERC20代币余额查询
所有合规的ERC20代币都实现了标准的balanceOf(address account)方法,Uniswap通过Multicall批量发起对目标代币合约的该方法调用:
- 调用构造:每个子调用的目标是对应ERC20合约地址,调用数据为
balanceOf方法的ABI编码(方法签名为0x70a08231,参数为待查询的用户地址) - Multicall的作用:将多个独立的
balanceOf调用打包成一笔链上交易执行,减少交互次数、降低gas消耗
示例代码片段:
// 构造USDC余额查询的调用数据 bytes memory usdcBalanceCall = abi.encodeWithSelector(IERC20.balanceOf.selector, userAddress); // 组装Multicall调用数组 Multicall3.Call[] memory calls = new Multicall3.Call[](1); calls[0] = Multicall3.Call({target: USDC_ADDRESS, callData: usdcBalanceCall}); // 执行批量调用 (bool success, bytes memory data) = MULTICALL_ADDRESS.call(abi.encodeWithSelector(Multicall3.aggregate.selector, calls)); // 解析返回的余额数据 uint256 usdcBalance = abi.decode(data, (uint256));
2. ETH余额查询
ETH是以太坊原生资产,没有对应的合约,但以太坊支持直接读取地址的balance属性。Uniswap通过Multicall执行视图逻辑来获取ETH余额:
- 可以构造一个指向Multicall合约自身的调用,在调用逻辑中读取目标地址的ETH余额;或者直接在Multicall的批量调用中嵌入读取
address(userAddress).balance的逻辑 - 本质是利用Multicall的视图执行能力,将余额读取操作打包到批量调用中
示例代码片段:
// 构造ETH余额查询的调用数据(假设Multicall合约实现了辅助方法) bytes memory ethBalanceCall = abi.encodeWithSignature("getEthBalance(address)", userAddress); // 组装调用数组 Multicall3.Call[] memory calls = new Multicall3.Call[](1); calls[0] = Multicall3.Call({target: MULTICALL_ADDRESS, callData: ethBalanceCall}); // 执行并解析结果 (bool success, bytes memory data) = MULTICALL_ADDRESS.call(abi.encodeWithSelector(Multicall3.aggregate.selector, calls)); uint256 ethBalance = abi.decode(data, (uint256));
为什么Multicall接口中找不到余额查询逻辑?
Multicall的定位是通用批量调用执行器,它的核心接口(如aggregate、tryAggregate)仅负责接收并执行传入的调用数组,不包含任何特定业务逻辑(比如余额查询)。余额查询的逻辑由两部分提供:
- ERC20余额:对应代币合约的标准
balanceOf方法 - ETH余额:以太坊原生的地址
balance属性
Multicall只是作为工具,将这些分散的查询操作打包执行,本身不承载业务逻辑,所以你不会在它的接口代码中找到余额查询相关实现。
内容的提问来源于stack exchange,提问作者Anthony
相关产品推荐
相关产品推荐

