这篇文章将介绍一些可以考虑删除的功能的例子。 功能列表 2300 gas 津贴这是什么?当一个合约调用另一个合约时,被调用的合约会得到 2300 gas 用于执行非常有限的操作(足够做一点计算和生成一条日志,但不够写满一个存储槽)为何引入?最初是为了让智能合约钱包在收钱时能自动生成一条日志。后来还被用于实现 “守卫” 功能以防止合约收到 ETH。有何问题?由于它设置的是固定的 gas 数量,因此只要 gas 价格可以调整,人们就没有办法确定这些 gas 到底能支持什么类型的计算。它并没有很好地满足设计意图,有两个原因。首先,很多用户仍然在使用外部账户,而外部账户并不会生成日志。其次,SELFDESTRUCT操作码绕过了津贴机制。从长远来看,通过账户抽象化,外部账户的作用将被弱化,并且SELFDESTRUCT操作码可能将被移除,但是在这两件事完成之前,它都只是一个不充分的解决方式。如何移除?有两种可能 —— 要么将 2300 改成 0(不支持子执行(child execution))要么不限制数量(子执行可以从父执行中获得全部的 gas 可用额度)移除有何副作用?如果我们移除子执行,那么这将需要在合约调用中添加一个笨拙的二分处置(two-clause mechanic),即 0 gas 解释为 0,任何其他数字解释为 “发送所有的 gas”。它还会破坏反接收守卫功能和日志记录。如果我们在执行中允许子执行获得全部的 gas,那么通过调用发送 ETH 会变成一个需要信任的操作,恶意合约可能会借此扰乱一些应用。不过,Solidity 文档已经建议大家用 withdrawal 模式代替transfer,这样就不会有任何风险了。如何消除顾虑?让所有的 ETH 转账,无论是来自调用还是SELFDESTRUCT(如果保留的话),都生成一条日志,这样钱包就不需要生成日志了增加一条规则,对于提供 0 gas 的调用,可看做是一个 “可以生成日志的STATICCALL”。这样就复制了在 gas 津贴的执行环境里实际做到的功能。剩余 Gas 额度可见性这是什么?GAS操作码允许合约查看当前的执行环境中还剩多少 gas 可用。CALL允许调用者为子上下文提供固定数量的 gas。为何引入?反对让CALL将父环境中剩余的全部 gas 都交给子环境的最主要原因是避免 “不可信任的调用”:即发送者不信任接受者的调用。 一个简单的例子是发送 ETH 给参与方的金融机制。另一个例子是 M-of-N 外部价格信息的输入机制(oracle),通过调用一些合约,在获得所有合约回复后取中位数作为输出。有何问题?其实绝大多数不可信任调用的用例都可以通过其他方式绕过去。对于转账,Solidity 文档已经建议大家用 withdrawal 模式代替transfer。M-of-N 外部价格信息的输入机制可以很容易地通过为每一个外部输入单独创建一笔交易实现。这会让 gas 重定价变得很难做,当操作码的gas消耗量发生变化,固定 gas 数量的调用可能会不够用。如何移除?让CALL可以自动将父环境的所有可用 gas 额度都交给子环境。GAS操作码只需简单地返回交易的初始 gas 数量。移除有何副作用?我们知道的 “不可信任调用的合法用例” 主要是第三方赞助调用(译者注:即元交易)。第三方发布一笔事务,事务中包含你希望的调用,当调用发生后,可以自动地向你扣费(你会公布授权他们这样做的签名)。这对用户没有任何 ETH 的智能合约钱包、混币者的隐私保护以及其他一些用例都很有用。我们需要一个有限 gas 数量的调用以确保最终的支付语句真正被调用,而不会因为 gas 不足而被回退。如何消除顾虑?矿工可以直接充当中介,如果交易最终没有付钱给他们,他们就可以直接丢弃事务。参见 Phil Daian 的工作,他创建了一个由第三方机器人构成的生态,矿工可以自动产生 “安全” 的批量交易。在协议内增加一个明确的 “第三方付款人” 的交易类型。参见 EIP 2711 的例子。 (责任编辑:admin) |