NFT 也能投票:ERC-5805 带委托的投票权接口 图 1
NFT 也能投票:ERC-5805 带委托的投票权接口 · 图 1

NFT 也能投票:ERC-5805 带委托的投票权接口

很多 DAO 把治理权挂在 NFT 上:一枚藏品一票,或者按属性加权。但每个项目把这套逻辑写在自己合约里,查询方式五花八门。ERC-5805(Voting with delegation)想统一这件事:给包括 ERC-721 在内的代币规定一套”当前票数、历史票数、总票数、委托给谁”的标准查询接口。该提案状态为 Stagnant(停滞),创建于 2022 年 7 月 4 日,依赖 ERC-712 与 ERC-6372。本文按标准文本讲机制,不构成任何参与治理或投资建议。

一组查询函数与一个委托动作

标准接口的分工大致是:getVotes(account) 查某地址此刻的票数;getPastVotes(account, timepoint) 查历史某时点的票数;getPastTotalSupply(timepoint) 查历史时点的总票数;delegate(delegatee) 把自己的票投给某个地址(可以是自己);delegates(account) 查某地址当前的受托人;还有配合 ERC-712 离线签名的 delegateBySig。注意”拥有代币”与”票数落在谁身上”被拆成了两条账——委托只挪动投票权,不转移藏品。

NFT 也能投票:ERC-5805 带委托的投票权接口 图 2
NFT 也能投票:ERC-5805 带委托的投票权接口 · 图 2

检查点:堵上”一票两投”

标准特意要求历史票数经过检查点(checkpoint)记录。文档举的例子很直白:没有检查点时,一个人可以先用这枚 NFT 投票,转手给新地址,再用新地址投一次。有了检查点,治理合约读取的是快照时点的记录,转手改变不了历史。查询参数的”时点”单位取决于合约的钟,按依赖关系走 ERC-6372 的披露——所以查历史票前,先问合约用区块还是时间戳计时。

和直接用 balanceOf 查资格差在哪

不少 NFT 项目直接用”当前是否持有”判定投票资格,这会错过两类状态:委托(持有人想让别人代投)与历史(投票窗口开启后才接手的人不该追溯拥有过去的票)。ERC-5805 的意义在于给这两类状态一套通用读法,让不同项目能用同一套治理前端。

Stagnant 状态该怎么读

“停滞”意味着提案在标准流程中失去推进动力,不等于生态里没人做 NFT 治理——相反,OpenZeppelin 的实现与各家治理框架早就内置了类似逻辑,只是各自写法不同。因此实际核验某枚 NFT 的投票权时,更常见的路径是直接读该治理合约源码:查快照函数、委托函数是否可用、票数权重规则(按枚、按属性还是按供应量)。不要因为某个接口名字不在 ERC-5805 清单里,就断定项目不支持委托或快照。

一个查询细节

规范里有个容易被忽略的规定:用 getPastVotes 查询时,传入的时点必须与合约自己的钟口径一致;查询大于等于当前钟值的时点应当回滚,查询更早时点则必须给出稳定答案——历史检查点一旦写下就应永久不变。这条”任何时间重放同一查询必得同一结果”的要求,正是链上治理可审计性的地基。与之配套,ERC-6372 让同一套查询接口能透明地挂到治理合约上:治理方无须猜代币用什么计时,读一次 CLOCK_MODE 就够。

委托这件事的双向账本

值得多留意委托机制的记账方式:委托发生时的规则是”从旧受托人的票数里减去、给新受托人加上”,并广播 DelegateChanged 与新旧受托人的票数变更事件;一份代币在同一时刻只能委托给一个受托人,这条排他规则正是防重复投票的另一半保障。delegateBySig 允许离线签名的委托由任何人代提交,规范特意要求签名里的 nonce 与链上记录一致并在成功后递增,配合 EIP-712 的域分隔符防止一条签名跨合约、跨链重放。对普通持有者,这些机制的实际含义是:委托给地址前,先确认受托人地址是自己的还是别人的,也确认这个选择会随事件公开——你的投票权归属在链上是透明的。

治理权查询接口影响的是”怎么验证你的票”,不是”你的票值多少”;参与治理前以合约代码为据,本文仅为机制科普,不构成投资建议。