Solidity 中的断言与要求?

Assert vs. require within Solidity?

我的理解是 "require" 会在失败时退还剩余的 gas,而 "assert" 不会。

虽然我有点困惑b/c剩余汽油是什么意思?我经常指定一个非常大的 gas limit,即使我调用的合约要求很少。

如果我要指定 4,700,000 gas limit,而只需要 50,000 gas,但是 "assert" 在调用的合约中失败,我会失去所有 4,700,000 gas 吗?

是的,您会损失全部(或接近)金额。 assert 实际上是由于完全出乎意料的事情而对交易进行的灾难性救助。它应该用于检查诸如确保你的合同没有以无效状态结束、避免除以 0、over/underflow 等

另一方面,

require 只会消耗到故障点为止的 gas。剩余的gas将被退还。

您指定的气体限制不应任意高。当您发起交易时,系统会发送您指定的全部气体,并在执行结束时将剩余的气体退还给您。您不仅在自己的合约中将自己暴露给 asserts,而且如果您从自己的合约中调用其他合约,您就会为该合约提供大量带宽,以使用您传递给它的 gas 做任何它想做的事情。

显示耗气量的示例:

pragma solidity ^0.4.16;

contract Test {
    function run(uint8 i) public pure {
        uint8 total = 0;

        for (uint8 j = 0; j < 10; j++)
          total += j;

        assert (i < 20);
        require (i < 10);

        for (j = 0; j < 10; j++)
          total += j;
    }
}

所有测试运行,gas limit = 5000000

测试 #1 - 运行(8):函数 运行s 成功 - 消耗了 1860 gas。

测试 #2 - 运行(15):函数通过断言,在要求时失败。只有第一个循环消耗了 运行 - 1049 gas。

测试 #3 - 运行(25):函数在断言时失败。同样,只有第一个循环是 运行 - 消耗了 4978536 gas(哎哟)。