【问题标题】:Solidity gas estimation - always out of gas when setting to 0Solidity 气体估计 - 设置为 0 时总是没有气体
【发布时间】:2021-01-14 12:09:31
【问题描述】:

我正在尝试找出解决此问题的方法,以处理交易确认订单并将值设置为0

pragma solidity ^0.5.17;

contract Test {
    uint256 amount;

    constructor() public {}

    function join() public {
        amount += 100;
    }

    function leave() public {
        amount -= 100;
    }
}

鉴于这些交易(在 ropsten 上测试):

tx 1) 呼叫加入 确认 amount == 100

tx 2) 呼叫加入(gas 价格 1) 待处理 amount == 100 should tx3 get mined first

tx 3) Call Leave (gas price 100) Pending amount == 0

但是,只要将 amount 设置回 0tx 2 就会始终失败并出现 out of gas 错误。如果该值高于0,则不会发生这种情况。我的理解是,将值设置为 0 状态而不是正整数会花费更多的气体,并且气体估计没有考虑到这一点。我已经尝试delete,希望这会返还gas以补偿太低的gas限制,但它仍然失败了。

有没有一种优雅的方式来处理这种情况?我能想到的唯一方法是高估所有join 交易的gas,这有其明显的缺点,或者永远不要将amount 设置回0

【问题讨论】:

    标签: ethereum solidity smartcontracts erc20


    【解决方案1】:

    你的观察是正确的。

    通过将其设置为 0,您可以删除存储空间并获得 gas 退款。这就是为什么它需要更少的气体。但是gas退款有上限,所以你不能用它来存储ETH。

    在槽中存储一个值需要 20,000 gas(来源:https://github.com/ethereum/go-ethereum/blob/d13c59fef0926af0ef0cff0a2e793f95d46442f0/params/protocol_params.go#L41

    从存储槽加载一个值需要 2,200 gas(来源:https://github.com/ethereum/go-ethereum/blob/d13c59fef0926af0ef0cff0a2e793f95d46442f0/params/protocol_params.go#L89

    这就是您看到不同气体消耗值的原因。

    只需将您的 gasLimit 设置为一些根据经验得出的粗略估计值。

    跟踪您的交易,您将看到所有的gas消耗值。

    现在,gas 退款的工作方式是,在状态转换功能期间,您需要为合同运行提供全部 gas。在此运行期间,所有 gas 退款都累积在 StateDB(临时状态对象)中。在状态转换功能结束时,您将获得合约将要进行的所有存储释放的退款。这就是为什么您必须设置 Etherscan 显示的更高 gas 限制的原因,因为假设您的合约需要 15,000 gas 才能运行,在存储释放后(例如 5,000 gas),Etherscan 将显示交易需要 10,000 gas。这不是真的,因为你在最后得到了 gas 退款,但一开始你需要全部的 gas(15,000)。 Gas 退款由矿工赞助,他的账户将获得更少的 ETH,因为他正在向您支付这些退款。

    【讨论】:

    • 感谢您的回复,这是有道理的。我不确定手动将 gasLimits 设置得更高以确保安全(交易“看起来”更昂贵的警告)是否是一种好习惯,或者将其留给供应商的 gas 估算。
    猜你喜欢
    • 1970-01-01
    • 2018-01-18
    • 2018-06-13
    • 2020-07-28
    • 2023-02-10
    • 2019-06-02
    • 2020-03-27
    • 1970-01-01
    • 2021-02-08
    相关资源
    最近更新 更多