跳到正文
fevou.独立加密知识站

代币销毁怎么查:转进黑洞地址和调用销毁函数,总供应量变不变

“已销毁”在链上有两种做法:把币转进 0x000…dEaD 这类地址,或者调用合约的销毁函数。两种做法在区块浏览器上留下的记录不一样,总供应量的读数也不一样。

编辑图解:标题文字为“说是销毁了,先分清是哪一种”,下方三格分别写着“转进黑洞地址”“调用销毁函数”“总供应量变没变”
说是销毁了,先分清是转进黑洞地址还是调用销毁函数,再看总供应量变没变。

项目方说“已销毁”,链上对应的可能是两种做法,总供应量的结果不一样。一种是把币转进项目方常用来销毁代币的地址,也就是常说的黑洞地址,比如 0x000…dEaD。这是一笔普通转账,币挪到了那个地址名下;按 OpenZeppelin 文档的实现,合约 totalSupply() 返回的数不变。另一种是调用合约的销毁函数;同样按这份文档,total supply 会降低,同时发出一条 to 为零地址的 Transfer 事件。

核对一句“已销毁 xx%”,要在区块浏览器上看四处:代币页的 Max Total Supply,持有人列表里销毁地址的余额、地址页上有没有 Burn 标签,转账记录里 to 为零地址的那些,合约源码里有没有 burn。CoinMarketCap 等行情站会按自己的供应量定义扣除已确认的销毁量,显示结果可能与合约读数不同。

黑洞地址里的币还算不算总供应量

按 OpenZeppelin 这套实现,算。OpenZeppelin Contracts 5.x 的 ERC-20 文档中,totalSupply() 返回现存代币的数量。以下 ERC-20 例子采用它未经自定义修改的基础实现:普通转账只在地址之间移动余额,不改变总量。

黑洞地址在链上也只是一个地址。Etherscan 上 0x000…dEaD 的地址页给它的名称标签是 “Null: 0x00...dEaD”,归在 Burn 标签下。转进去的币仍然记在它的余额里,在持有人列表里查得到。

地址页说明项目方常用它销毁代币,并把这称作供应量减少。对前述基础实现而言,减少的是扣除这个地址余额后的统计数;合约里的 totalSupply() 仍要单独读取。

所以这种做法下的“已销毁多少”,是一个加出来的统计数:选定一组销毁地址,把它们的余额相加。算进了哪些地址、哪一天加的,结果都跟着变。

要确认的是这笔币还会不会回到市场。转进黑洞地址的币没有从合约里消失,它以后能不能再动,取决于有没有人能控制那个地址。Burn 标签描述的是地址用途;公告里给的如果是别的地址,它带什么标签、是普通账户还是合约、有没有转出过这个币,都要自己看一遍。

零地址 0x0000…0000 是另一个地址,别和 dEaD 当成同一个。Etherscan 给它的名称标签是 “Null: 0x000...000”,带 Blocked、Burn、Genesis 三个标签,说明它不属于任何用户,常和代币的销毁、铸造、创世事件连在一起。它出现在销毁事件的 to 栏里,并不表示零地址账户收到了这笔币。

调用 burn 函数销毁,链上会留下什么

在前述实现中,销毁非零数量会留下两样:变小的 total supply,以及 to 为零地址的 Transfer 事件。

ERC20Burnable 扩展让持有人销毁自己的币,也让拿到授权的人销毁授权范围内的币。销毁留下的事件可以在链下分析,所以查记录时能找到具体数量和相关账户。

它对外给了两个函数:

  • burn(uint256 value):销毁调用者自己的币。
  • burnFrom(address account, uint256 value):销毁另一个账户的币,需要足够的授权额度。有限额度会扣减;设为 uint256 最大值的无限授权不会因此递减。

内部函数 _burn 负责减少账户余额和总量,并发出上述 Transfer 事件。

铸造是反方向:_mint 发出的 Transfer 事件,from 是零地址。在这套实现下翻转账记录,from 为零地址的对应新增,to 为零地址的对应销毁。

普通的 transfer 要求收款方不是零地址,因此可以转到 dEaD,却不能直接转到零地址。看事件里的 to,就能分开这两种记录。

ERC-20 标准没有规定销毁

上面这些是 OpenZeppelin 一家实现的行为。ERC-20 标准(EIP-20)定义了 9 个方法和 2 个事件,全文没有出现 burn 或 destroy 这两个词。它对 totalSupply 只有一句 “Returns the total token supply.”;对新造出来的代币,写的是应当(SHOULD)触发一条 from 设为 0x0 的 Transfer 事件。销毁没有统一的函数名,也没有统一的“已销毁数量”查询项。

别的合约可以写得不一样,比如允许转进零地址,或者对某个地址做特殊处理。某个币的销毁属于哪一种,从标准里推不出来,要读它自己的代码。

假设销毁 20%:两种做法下 totalSupply 各是多少

假设一个代币的 totalSupply() 是 1,000,000,000 枚,合约按 OpenZeppelin 的方式实现,0x000…dEaD 的余额原本是 0。项目方宣布销毁 200,000,000 枚,占 20%,此外没有别的增发和销毁。

销毁后去看转进 0x000…dEaD调用销毁函数
这笔操作在转账记录里一条 Transfer 记录,to 是 0x000…dEaD一条 Transfer 记录,to 是零地址
totalSupply() 返回1,000,000,000(不变)1,000,000,000 − 200,000,000 = 800,000,000
0x000…dEaD 的余额200,000,0000
可流通量(本例按 totalSupply() 减黑洞地址余额算)1,000,000,000 − 200,000,000 = 800,000,000800,000,000 − 0 = 800,000,000
黑洞地址占 totalSupply() 的比例200,000,000 ÷ 1,000,000,000 = 20%0 ÷ 800,000,000 = 0%

第四行两边相等,扣掉黑洞地址之后剩下的币都是 800,000,000 枚。差别在页面读数上。第一种做法,总供应量还是 10 亿,持有人列表里多出一个占 20% 的地址。第二种做法,总供应量变成 8 亿,持有人列表里找不到这笔币,要去转账记录里找那条 to 为零地址的事件。

你的持仓占比也会因此有两个算法。假设你持有 8,000,000 枚。第一种做法下,按 totalSupply() 算是 8,000,000 ÷ 1,000,000,000 = 0.8%,把黑洞地址的 2 亿扣掉之后是 8,000,000 ÷ 800,000,000 = 1%。第二种做法下,按 totalSupply() 直接算就是 1%。

听到“销毁 20%”,要追问的是表里哪一行变了。总供应量降到 8 亿,和总供应量仍是 10 亿但有 2 亿停在黑洞地址,转述出来是同一句话。

在区块浏览器上查销毁,看这四处

以 Etherscan 这类区块浏览器的代币页为例。四处读数都抄下来,旁边写上查看的日期。

  1. Overview 里的 Max Total Supply。先记下页面显示值,再到 Contract → Read Contract 读取 totalSupply,并按 decimals 换算成枚;若是代理合约,应通过代理地址的 Read as Proxy 读取。把读取时间和结果一起记下,别只凭栏目名称认定它等于当前合约读数。
  2. 持有人列表里的销毁地址。代币页简介区如果有 Burn Address(es) 一栏,先照那一栏记;再点进每个地址的地址页看有没有 Burn 标签,逐个记下地址和余额。公告里给的“销毁地址”如果没有 Burn 标签,照样记下,再看这个地址有没有转出过这个币。
  3. 转账记录里 to 为零地址的那些。按 OpenZeppelin 的实现,销毁函数每执行一次就留下一条。点开看数量、发起地址和日期,和公告对不对得上。
  4. 合约源码里有没有 burn。搜 burn,看有没有对外的销毁函数,谁能调用,销毁时有没有降低 total supply。

第 4 步需要找到与当前链上代码匹配的源码。这家浏览器未验证,源码仍可能在项目仓库或其他验证服务公开;核不出对应关系时,销毁逻辑记“未确认”。代理合约还要查看当前实现,验证状态怎么看,见 代币合约没开源是什么意思。函数名是发行方自己起的,搜不到 burn 这个词,也不能直接记成“没有销毁函数”。

四处读数放在一起才看得出是哪种做法。已核明普通转账逻辑、总量不变,且对应数量转进了 Burn 地址,可归为转地址的做法。事件的 to 是零地址时,再结合实现代码确认它代表销毁。一个代币两种都用过也说得通,那就两边的数量分开记。

记下来的东西大致是这几行:

  • 总供应量读数,查看日期。
  • 每个销毁地址、余额、有没有 Burn 标签。
  • to 为零地址的记录有几条、数量合计多少、最近一条是哪天。
  • 源码验证状态;销毁函数写“有”“没搜到”还是“未确认”。

Total Burned 和总供应量对不上,行情站又是另一个数

这几个数算法不同,日期也不同,不能直接互相加减。拿 Etherscan 上 SHIBA INU(SHIB)的代币页当样本,看这类页面长什么样;本文引用的页面和下面的读数查阅于 2026 年 10 月,读数以页面实时显示为准。

  • Overview 里的 Max Total Supply:999,982,329,055,139.380064881851651014 SHIB,约 999.98 万亿枚。
  • 简介区 Burn Events 一块里的 “Total Burned : 401,710,298,254,976.58589 SHIB as of Aug 15, 2024”,约 401.71 万亿枚。
  • 同一块里的 “Circulating Supply : 589,261,465,289,188 SHIB as of Aug 15, 2024”。
  • 市场数据区另有一个 “Circulating Supply: 589,238,379,573,543.00 SHIB”,标注 “Market Data Source: Coinmarketcap”。

Total Burned 没有从 Max Total Supply 里减掉

Max Total Supply 约 999.98 万亿枚,页面另列的 Total Burned 约 401.71 万亿枚,后者没有从前者里减掉。页面还提示到 Info 标签查看销毁后的供应量。Burn Events 列有地址与日期,但不能仅凭这份列表认定其统计数就是各地址当前余额之和。

销毁地址列了 10 个,dEaD 只占很小一部分

“Burn Address(es)” 一栏列了 10 个地址缩写。第一个是 0x0000...dEaD,最后一个是 0x95aD...C4cE,首尾和这个代币的合约地址相同。用持有人筛选单看 0x000…dEaD:余额 49,479,931,109.106133396429082525 SHIB,约 494.8 亿枚,占比 0.0049%。和约 401.71 万亿枚的 Total Burned 放在一起,它只占很小一部分。查销毁只盯一个黑洞地址,会漏。

三个数不是同一天的读数,别硬凑成等式

Total Burned 和 Burn Events 里的 Circulating Supply 标的是 2024 年 8 月 15 日,Max Total Supply 是打开页面当时的数。把前两个相加(小数取两位):589,261,465,289,188 + 401,710,298,254,976.59 = 990,971,763,544,164.59,和 999,982,329,055,139.38 差约 9.01 万亿枚。页面没有解释这笔差额,不要自己猜一个原因填上去。市场数据区那个 Circulating Supply 也和 Burn Events 里的不是同一个数,来源标的是 Coinmarketcap。

CoinMarketCap 的 Total Supply 按定义是减过销毁量的

CoinMarketCap 帮助中心讲供应量的一页把 Total Supply 定义为现存币量扣除可验证的销毁量,也称 Minted/Issued Supply。Max Supply 的定义里也带同一个减项。它写的是“可验证地销毁”,怎么验证由它按自己的方法判断。

所以币转进黑洞地址之后,按 OpenZeppelin 的实现合约的 totalSupply() 没动,行情站的 Total Supply 却可能已经减掉了这部分。两边数字不同,各自按各自的定义读,不必认定哪一边错。流通量、总供应量、最大供应量三个词的区别,在 代币流通量、总供应量、最大供应量有什么区别。

Solana 上销毁代币:供应量怎么变,谁有权销毁

Solana 上的销毁用的是 Token Program 的 Burn 或 BurnChecked 指令,执行后代币账户余额和 mint 的供应量一起减少。Solana 官方文档的“销毁代币”页给出了余额与供应量如何一起减少的说明:

Solana 官方文档中文版“销毁代币”页顶部:页面标题“销毁代币”,小节标题“销毁有什么作用?”,以及一句“销毁代币会永久减少代币账户余额,并将铸币的总供应量减少相同数量。”
Solana 文档的销毁说明:账户余额与 mint 总供应量减少相同数量。截图:2026 年 10 月。

中文页把 mint 译作“铸币”。它保存该代币的供应量;销毁指令使账户余额和这个供应量同时减少,效果对应前面调用销毁函数的那一种。

核对一笔 Solana 上的销毁,看两处:那笔交易里的指令是不是 Burn 或 BurnChecked,mint 的供应量有没有减少相同的数量。交易里只有转账、没有这两条指令,就不是文档说的销毁。

原生 mint 例外:它不支持 Burn,文档给出的操作是 CloseAccount,不能把它当成普通代币的销毁来算。

通常由代币账户所有者,或者经其批准的 delegate 签名。

Token Extension Program 里还要查 permanent delegate 扩展。mint 启用它时,这个永久代理也能授权销毁。换到持币人这边说:币在你的代币账户里,有权把它销毁掉的却可能不止你和你批准过的 delegate。

查 Solana 代币时,mint 有没有启用这个扩展要单独看。你用的区块浏览器上要是读不出扩展信息,这一项记“未确认”。

销毁之后还要查什么

还能不能再增发。销毁函数降的是此刻的 total supply,合约里要是还留着铸造的权限,烧掉的数量之后还可能再铸出来。谁有这个权限,查法在 在区块浏览器上查代币管理权限。

“销毁 LP”是另一回事。公告里的“销毁 LP”“烧池子”,处理的是流动性池的 LP 凭证,不是这个代币的总供应量,查法见 流动性池锁仓怎么查。

黑洞地址排在持有人前列时,占比要重新算。币转进黑洞地址的那种做法,这个地址会出现在持有人列表里,前面算例里它一个地址就占 20%。看前几名合计占多少时,它算不算进去、分母用哪个数,见 持币集中度怎么看。

关于查销毁,再答三个具体问题

以太坊上,别人能销毁我钱包里的币吗?

按 OpenZeppelin 文档的实现,burnFrom 可以销毁另一个账户的币,但要求调用者拿到的授权额度(allowance)不少于要销毁的数量,有限额度会随销毁扣减;uint256 最大值表示无限授权,其额度不递减。你没有给过对方授权,对方就不满足这条要求。别的合约可以写得不一样,要看那个合约自己的代码;找不到与当前链上代码匹配的源码时,这一项记未确认。

合约源码里搜不到 burn,是不是就没法销毁?

不能这样下结论。ERC-20 标准没有规定销毁,也没有统一的函数名,销毁逻辑可能写在别的名字下面。另外,把币转进 0x000…dEaD 这类地址只是一笔普通转账,不需要合约有销毁函数;按 OpenZeppelin 文档的实现,这样做合约的 totalSupply() 不变。

项目说销毁了百分之几,这个百分比按哪个数算?

没有统一算法。ERC-20 标准没有规定销毁,也没有统一的“已销毁数量”查询项,百分比由发布的人自己选分母。核对时问清分母是销毁前的总供应量还是别的数,再拿你在区块浏览器上记下的销毁数量自己除一遍。假设销毁前总供应量是 1,000,000,000 枚、销毁 200,000,000 枚,按销毁前总量算是 20%。