开源项目
ensdomains/ens-contracts avatar
ensdomains/ens-contracts

ens-contracts 代码库剖析:ENS 核心合约的结构、迁移与适用边界

ENS 协议的核心合约。 DNSResolver = 实验性支持可用于通过 ENS 在以太坊区块链上托管 DNS 域。

728 个 Star578 个 ForkTypeScriptMIT

秒懂

它是什么?
本文基于 ensdomains/ens-contracts 仓库的 README 与近期发布记录,拆解 ENS 协议中注册表、.eth 注册器、解析器三大模块的实际分工,并指出它在多链场景下的局限性。
适合谁用?
ens-contracts 适合需要直接部署或继承 ENS 注册表、.eth 注册器或通用解析器的以太坊开发者,尤其是那些希望复用经过审计的合约逻辑、并依赖 npm 包中预编译 artifact 的项目。不适合需要多链支持、或需要深度定制注册流程的团队,因为仓库默认只面向以太坊主网与测试网,且注册器控制器机制要求额外开发自定义控制器。
能商用吗?
可以。MIT 是宽松许可证:你可以使用、修改并销售基于它的软件,只需保留版权和许可证声明。
还在维护吗?
在维护。仓库最近一次提交在 1 天前。
用什么语言写的?
主要是 TypeScript(依据 GitHub 的语言统计)。

以上回答依据项目的 GitHub 数据(最近同步于 2026年9月15日)和我们的分析,不构成法律意见。

开源项目深度解析

一个仓库,三个职责:注册表、注册器与解析器

ens-contracts 不是单一合约,而是 ENS 协议的 Solidity 实现集合。README 明确将合约划分为 Registry、EthRegistrar、Resolvers 三大块。注册表负责维护域名到所有者、解析器、TTL 的映射,是所有解析查询的起点。注册器处理 .eth 域名的注册与续期,其中 BaseRegistrar 持有 TLD,而 EthRegistrarController 实现具体的注册逻辑。解析器则把域名映射到地址、文本记录、内容哈希等数据。这种分层让不同部分可以独立升级,例如新解析器无需改动注册表。但代价是理解整条调用链需要分别阅读多个合约,入门成本并不低。

commit-reveal 机制:防抢跑的具体做法

EthRegistrarController 使用 commit-reveal 流程来避免注册时被 frontrunning。用户先提交一个哈希,这个哈希的预映像包含要注册的域名和一个秘密值。经过最小延迟后,在承诺过期前,用户调用 register 函数并传入域名和秘密值。合约验证承诺是否存在且有效,再完成注册。最小延迟和过期时间的存在,是为了防止矿工或其他用户观察交易池后抢先注册。这个机制在 README 中有明确说明,但未给出具体的延迟数值。实现时你需要自行查阅合约源码中的 MIN_COMMITMENT_AGE 常量。对于普通用户而言,这个流程意味着注册 .eth 域名至少需要两次交易,体验上比传统 DNS 注册更繁琐。

价格预言机的设计:固定价格与稳定价格的分歧

控制器依赖一个价格预言机合约来决定注册和续期的费用。SimplePriceOracle 总是返回合约所有者设定的固定价格,适合测试或内部场景。StablePriceOracle 则根据名称长度定价,并使用法币预言机将价格锚定在法币上。README 没有说明 StablePriceOracle 具体如何获取法币汇率,只提到它使用一个 fiat currency oracle。这意味着如果你要部署自己的实例,必须额外提供一个可信的汇率源合约。价格预言机是可替换的,控制器所有者可以随时设置新的预言机地址,这提供了灵活性,但也引入了治理风险:如果所有者被恶意控制,价格可以被任意操纵。

解析器中的实验性功能:DNSResolver 的边界

PublicResolver 实现了多个 EIP 定义的接口,包括地址解析(EIP 137)、多币种支持(EIP 2304)、内容哈希(EIP 1577)和文本记录(EIP 634)。其中 DNSResolver 被明确标注为实验性支持,用于在以太坊区块链上托管 DNS 域名。README 指向了一份旧文档,说明该功能并非生产就绪。如果你的项目需要将传统 DNS 域名迁移到链上,这个实验性状态意味着接口可能变动,且缺乏审计保证。相比之下,其他解析器接口都有对应的 EIP 编号,稳定性更高。因此,DNSResolver 更适合技术验证,而非直接用于面向用户的 DNS 服务。

部署与集成:从 npm 包到 Hardhat 构件

仓库同时作为 npm 包发布,提供了编译后的 JSON 合约文件。你可以在 JavaScript 中直接导入 BaseRegistrar、ENSRegistry、PublicResolver 等合约对象,也可以在 Solidity 中通过 import 语句引用源码。对于没有编译器的环境,README 建议直接访问 node_modules 下的 artifacts 目录,路径格式为 artifacts/contracts/${modName}/${contractName}.sol/${contractName}.json。这意味着你可以跳过 Hardhat 编译步骤,直接使用预构建的 ABI 和字节码。但要注意,这些 artifact 对应的是仓库默认分支的编译结果,如果你需要修改合约参数,仍需自行编译。开发者指南提到使用 husky 和 prettier 来保持代码格式一致,这属于维护细节,不影响部署流程。

版本演进与迁移成本:从 v1.5.2 到 v1.7.0

最近三个版本分别是 v1.5.2(2025-06)、v1.6.0(2025-09)和 v1.7.0(2026-03)。v1.7.0 的发布距离 v1.6.0 有六个月,说明开发节奏并不快。仓库默认分支是 staging,这意味着主分支可能不是最稳定的版本。对于依赖此仓库的开发者,升级时需关注合约地址是否变化,因为 ENS 注册表在 2020 年经历过一次迁移,新版本可能引入新的部署地址。README 提到 ENSRegistryWithFallback 是 2020 年迁移后的新实现,但没有说明 v1.7.0 是否改变了注册表逻辑。如果你已经部署了基于旧版本的合约,升级前必须对比两个版本的 diff,否则可能破坏现有域名的解析。

许可证与审计:MIT 许可下的使用自由与责任

仓库采用 MIT 许可证,这意味着你可以自由使用、修改和分发代码,只需保留版权声明。README 提到 EthRegistrar 合约经过 ConsenSys Diligence 审计,并提供了审计报告链接,但该审计针对的是 2019 年 2 月的版本。此后合约经历了多次迭代(包括 v1.5.2 到 v1.7.0),新代码是否经过同等程度的审计并不明确。对于资金相关的合约,尤其是处理用户注册费用的部分,你应该自行审查最新版本,或等待官方发布新的审计报告。MIT 许可证不提供任何担保,使用方需承担合约漏洞的风险。

编辑结论

ens-contracts 适合需要直接部署或继承 ENS 注册表、.eth 注册器或通用解析器的以太坊开发者,尤其是那些希望复用经过审计的合约逻辑、并依赖 npm 包中预编译 artifact 的项目。不适合需要多链支持、或需要深度定制注册流程的团队,因为仓库默认只面向以太坊主网与测试网,且注册器控制器机制要求额外开发自定义控制器。采用前应验证:目标链是否兼容 Solidity 版本与硬分叉规则(特别是 EIP-1559 后的价格计算),并检查 v1.7.0 与 v1.6.0 之间的变更日志,确认 DNSResolver 的实验状态是否影响你的域名场景。

官方来源

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
社区笔记

社区笔记