You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ERC20代币余额在以太坊链上的存储机制及副本数量咨询

关于ERC20代币余额在区块链上存储方式的解析

嘿,这个问题确实戳中了很多人对区块链状态存储的误解点,我来一步步给你拆解清楚~

首先明确:合约的mapping不是“表”,而是独立的存储槽集合

你看到的mapping(address => uint) balances,在EVM(以太坊虚拟机)的底层逻辑里,并不是一个包含所有记录的大表格。它更像是一个“计算规则”:当你要查询某个地址的余额时,EVM会通过该地址和mapping的存储位置,计算出对应的唯一存储槽(一个256位的哈希值),然后从合约的存储空间里读取这个槽的值。

也就是说,balances里的10000条记录,其实是10000个独立的键值对(存储槽地址 => 余额数值),只有当某个地址有过余额变更(比如接收过代币)时,这个存储槽才会被创建并写入数据。

区块链上的“副本”是怎么回事?

区块链的全节点会保存完整的链数据,但这里的“副本”不是指每个区块都存一份完整的balances:

  • 每个区块只记录状态变更的增量:当你发起转账修改了2个地址的余额时,新区块里只会记录这两个存储槽的新值,而不是整个balances的副本。
  • 全节点维护的是当前最新的状态快照:所有节点都会基于上一个区块的状态,应用新区块里的所有交易变更,得到最新的合约存储状态。比如区块100的状态是A,区块101包含你的转账交易,节点就会把A中对应两个存储槽的值修改,得到状态B,然后只保留状态B作为当前最新状态(普通节点不会保存所有历史状态,归档节点才会)。

转账后的具体状态变化过程

当你的转账被打包进区块101并确认后:

  1. EVM执行这笔交易,找到转出地址和转入地址对应的balances存储槽。
  2. 把转出地址的存储槽值减去转账金额,转入地址的存储槽值加上转账金额。
  3. 新区块会记录这次状态变更的相关信息(比如交易哈希、变更的存储槽和新值),但不会保存整个balances的完整副本。
  4. 所有全节点同步区块101后,都会更新自己维护的合约存储状态,将这两个存储槽的值替换为新值,其他9998个存储槽的内容完全不变。

关键补充:mapping的存储槽计算逻辑

为了让你更明白,举个简单的计算方式(假设balances是合约的第一个存储变量,索引为0):
每个地址addr对应的balances[addr]存储槽地址是:

keccak256(abi.encodePacked(uint256(uint160(addr)), uint256(0)))

这个哈希值是唯一的,所以每个地址的余额都存在独立的位置,修改时只会影响这一个位置,不会触动其他存储槽。

内容的提问来源于stack exchange,提问作者KurtZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:22:20