搜索
输入以搜索 · Esc 关闭

合约真的不可更改吗?

几乎每个项目都说自己的合约无法更改。这个说法异常容易核实,正因如此才值得去核实而不是相信。它只需几分钟,也不需要特别的工具。

这个词必须意味着什么

不可更改只意味着一件事:今天在某个地址上执行的代码,明天仍然是在那里执行的代码,而且没有人能把它换掉。团队不能,投票不能,守护者不能,紧急状况也不能。只要存在任何一条能改变被执行代码的路径,该合约就是可升级的——这是一种正当的设计选择,但那是另一回事,就该用那样的词来描述。

问题从来不是抽象地"他们能不能改"。问题是:他们会用哪一个具体机制,而这个机制在这个地址上是否存在?

说法通常在哪四处不成立

  • 代理。你打交道的地址并不含逻辑;它把每一次调用转发到它所存储的另一个地址。改掉所存的地址,行为就整个变了,而给你的那个地址纹丝不动。这是所有例外中最常见的一种,且遥遥领先。
  • 拥有权限的所有者。逻辑固定了,但特权函数允许所有者更改费率、暂停转账、增发或调动资金。代码没有变;它做的事照样变了。
  • 模块或注册表。核心固定了,但它从另一个并不固定的合约读取参数,或把一部分工作委派给它。可变的那一部分只是挪到了一个地址之外。
  • 没有终点的暂停。一个没有自动到期、也没有解除义务的紧急停止,实际上就是终结协议的权力。它在代码里什么也没改,在"你能做什么"上却改变了一切。

按顺序如何核实

  • 源码是否已验证?在区块浏览器上,该地址应显示与已部署字节码相符的已验证源码。若没有,下面的一切都无法核实,到此为止即可。
  • 它是代理吗?浏览器通常会直接说明。若没有,就去找实现槽、会委派的回退函数,或升级函数。代理不是缺陷,但它把问题转移成了"谁能调用升级"。
  • 存在哪些特权函数?读一遍带访问修饰符的函数清单。对每一个都问:它能对持有该代币的人做出的最坏的事是什么?
  • 特权地址掌握在谁手里?所有者地址是一个带时间锁的多重签名钱包,与是一把单独的私钥,风险完全不同。二者又都不同于所有者已被设置为无人控制的地址。
  • 是否存在只在构造时设定的路径?在部署时固定、此后再不写入的数值,是最强形式的不可更改,并且在代码里一眼可辨。

五个步骤,每一步都能由浏览器和源码作答。走完之后,你没有相信任何人的任何话,并且能准确说出什么可能变、什么不可能变。

不可更改给不了你什么

关于边界值得说清楚,因为这个词有时被用得好像它解决了一切。不可更改的合约里照样可能有缺陷,而不可更改恰恰意味着这个缺陷同样无法修补。它对代码质量只字未言,对合约所依赖的资产只字未言,对经济学是否成立也只字未言。

它给你的是另一样东西:一个不动的评估对象。你今天对这段代码得出的任何结论,明天对它依然成立。这很有价值,但它不等于安全。

Common questions

可升级的合约是坏兆头吗?

本身不是。可升级让团队能够修补缺陷,而不可更改做不到。要紧的是它是否被如实披露,以及由谁掌控。被称作"不可更改"的可升级合约,才是坏兆头。

放弃所有权会让合约变得不可更改吗?

它移除了所有者的权限,这是其中一部分。但如果合约位于一个管理员另有其人的代理之后,在逻辑合约上放弃所有权,丝毫不改变谁能替换那段逻辑。

投票能改变一个不可更改的合约吗?

只有在合约本身包含允许这样做的机制时才能。对合约所交付投票的参数的治理,与对代码的治理不是一回事,这个区别应当双向讲清楚。

本项目在这件事上的位置

Assetrix 以不可更改的合约部署,没有升级路径,也没有代理;本节中的任何内容都不要求你凭信任接受这一点:上面那套核实方法对它完全适用,就像对其他任何合约一样——在合约部署并完成源码验证之后。

存在两个角色,其权限是被逐条列出的而非笼统描述的:守护者任命和罢免操作员;操作员在代码中固定的上限内设定协议费、公布币种以供投票,并可在持有者确认的前提下启动储备损失标志。二者都不能更改铸造价格、增长阶梯或支撑规则,不能对头寸赎回引入费用,不能违背投票接纳币种,也不能停止资金返还。最后这几项是合约的属性,不在任何角色和任何投票的触及范围之内。

最新