开发者指南 · Zikaron

登记合约与上链

登记合约只做一件事:收到指纹,发出一条事件。法读取的是事件的格式。

接口

event Anchored(address indexed author, bytes32 indexed hash); function anchor(bytes32 hash) external; function anchorMany(bytes32[] calldata hashes) external;

anchor 发出一条事件;anchorMany 为数组中的每个元素各发一条,空数组发出零条。事件中的 author 是调用者地址。合约零存储、零所有者、零升级入口,对所有调用者一视同仁。源码在 base/zikaron-core/contracts/src/ZikaronRegistry.sol,许可为 CC0-1.0。

已知部署

应用内置两处部署,同一份钉定的构建,代码哈希相同:

网络链号登记合约起始区块
以太坊主网(默认)10x36Ea8A857a5FE813429d4D9947000C644A88809A26087229
Sepolia 测试网111551110xC29410B882c4C3b77e33659d2f06ac563e7B08a311715660

起始区块是扫描的起点,早于这个合约上的第一条上链记录。

两种上链形式

登记形式
交易成功,且回执中有一条由登记合约发出的日志:恰有三个主题、数据为空;主题 0 为 Anchored(address,bytes32) 的 keccak256,主题 1 为交易发送者,主题 2 为指纹。同一指纹还须出现在交易的调用数据中,起始偏移为 32 的整数倍,或 4 加 32 的整数倍。
自转账形式
一笔发给自己的交易,调用数据长度为 32 的正整数倍,每 32 字节为一个指纹。只依赖交易本身,适用于任何 EVM 链。

两种形式效力相同。核验方在自己的扫描范围中写明认可哪些登记合约地址、哪些发送者、哪些自转账交易。

对发送者的三项要求

  • 发送者是由交易签名恢复出的地址。经中继代发的交易,发送者为中继地址;由账户代码验证的交易,在法中发送者一项为空。
  • 发送地址在上链所在区块前后均为普通地址。带有代码或 EIP-7702 委托的地址发出的上链记录,一律作废。
  • 交易签名中写明链号。

这三项保证一条上链记录始终可以读作「这把密钥本人所为」。

代码哈希

合约的运行时字节码长 246 字节,其 keccak256 为:

代码哈希0xfa97a1d9b22fab2b52f4e27c9a965b32734c40001b565ab365d05c887118f57d

它由固定的编译设置产生:solc 0.8.28,EVM 版本 cancun,开启优化(200 轮),开启 via_ir,字节码去除元数据。源码或设置的任何改动都会改变哈希。自行重算:

cd base/zikaron-core/contracts forge build cast keccak $(forge inspect ZikaronRegistry deployedBytecode)

自行部署

任何人都可以在任一已完成上海升级的 EVM 链上部署相同的字节。部署后核对链上代码哈希与上表一致,再在应用的「设置 › 网络 › 编辑节点…」里填入链 ID、登记合约与起始区块。

forge create src/ZikaronRegistry.sol:ZikaronRegistry \ --rpc-url <节点> --private-key <部署用的密钥> --broadcast cast keccak $(cast code <新地址> --rpc-url <节点>)

部署请用专门的密钥;身份密钥只用于签署账本和发送上链交易。

这份固定构建使用 PUSH0 指令,适用于已完成上海升级的链。更早的链须另行构建,代码哈希也随之改变。法按核验方声明的合约地址读取日志,因此另一份构建只关乎部署的便利。

费用参考

调用合约执行消耗的 gas
anchor2,352
anchorMany,1 条2,776
anchorMany,10 条17,746
anchorMany,100 条167,661

表中是在 forge 里测得的合约执行部分,交易的 21,000 基础费用与调用数据费用另计。条数越多,单条分摊越少。应用发送时 gas 上限定为 200,000。

经其他合约上链

任何合约只要发出同样格式的日志,都可充当登记合约。以下三个条件同时成立,该日志才算上链记录:交易由账本密钥亲自发出;指纹出现在该交易自身的调用数据中,且位置符合上述规定;日志由被调用的合约自身发出。合约在内部转而调用登记合约时,日志记录的是那个合约的地址,对任何账本而言都只是一条普通日志。

核验方只应把读过源码、代码固定的合约地址写入扫描范围。

自含上链证明

法 §9.7 定义了自含的上链证明,记录包的 proofs/ 目录用于携带。凭这样一份证明,核验方只需两个可信的区块哈希即可验证一条上链记录:区块头,交易与回执各自的默克尔证明,以及发送地址在前后两个区块中的账户证明。节点清理历史数据后,此类证明依然有效。