Оценка твердого газа - всегда нет газа при установке на 0

Я пытаюсь найти решение этой проблемы, связанное с порядком подтверждения транзакции и установкой значений 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) Присоединение к вызову (цена газа 1) Ожидание amount == 100 should tx3 get mined first

tx 3) Call Leave (цена газа 100) Ожидает amount == 0

Однако tx 2 всегда будет завершаться ошибкой out of gas до тех пор, пока amount не будет установлено обратно на 0. Этого не происходит, если значение превышает 0. Насколько я понимаю, установка значения в состояние 0 вместо положительного целого числа стоит больше газа, и оценка газа не принимает это во внимание. Я пробовал delete, надеясь, что это даст возмещение за газ, чтобы компенсировать слишком низкий лимит газа, но это все равно не удалось.

Есть ли элегантный способ справиться с этим сценарием? Единственные способы, которые я могу придумать, — это переоценить газ для всех join транзакций, что имеет свои очевидные недостатки, или никогда не возвращать amount к 0.


person Boyswan    schedule 14.01.2021    source источник


Ответы (1)


Вы делаете правильные наблюдения.

установив его на 0, вы удалите хранилище и получите возврат газа. Вот почему требуется меньше газа. Но возврат газа имеет верхний предел, поэтому вы не можете использовать его для хранения ETH.

Хранение одного значения в слоте стоит 20 000 газа (источник: https://github.com/ethereum/go-ethereum/blob/d13c59fef0926af0ef0cff0a2e793f95d46442f0/params/protocol_params.go#L41 )

загрузка одного значения из слота хранилища стоит 2200 газа (источник: https://github.com/ethereum/go-ethereum/blob/d13c59fef0926af0ef0cff0a2e793f95d46442f0/params/protocol_params.go#L89)

Вот почему вы видите разные значения расхода газа.

Просто установите свой gasLimit на какое-то эмпирически найденное приблизительное значение.

Сделайте трассировку своей транзакции, и вы увидите все значения потребления газа.

Теперь способ возврата газа заключается в том, что во время функции перехода состояния вас просят полностью заправиться газом для выполнения вашего контракта. Во время этого прогона все возвраты газа накапливаются в StateDB (временный объект состояния). В конце функции перехода состояния вы получите возмещение за все выпуски хранилища, которые будет выполнять ваш контракт. Вот почему вы должны установить более высокий предел газа, который показывает Etherscan, потому что, допустим, вашему контракту требуется 15 000 газа для работы, после освобождения хранилища (скажем, для 5 000 газа) Etherscan покажет, что для транзакции требуется 10 000 газа. Это неправда, потому что в конце вы получили возмещение за газ, а в начале вам был нужен весь объем газа (15 000). Возврат газа спонсируется майнером, его счет получит меньше ETH, потому что он платит вам эти возмещения.

person Nulik    schedule 14.01.2021
comment
Спасибо за ответ, это имеет смысл. Я не был уверен, является ли хорошей практикой вручную устанавливать более высокие лимиты газа, чтобы быть в безопасности (с оговоркой, что транзакции «кажутся» более дорогими) или оставить это на усмотрение поставщиков газа. - person Boyswan; 14.01.2021