После проблемы, которую я открыл в github, это меня беспокоит. Операция, описанная в проблеме, которая произошла во время следующего руководства avsa по созданию DAO, сгенерировала две внутренние транзакции, как видно здесь: Вкратце, внутренние транзакции:
Первая внутренняя транзакция завершена успешно — это означает обновление операции в DAO до статуса «завершено». Второй терпит неудачу, скорее всего, потому, что у него закончился газ (несколько попыток дали одинаковые результаты, а добавление 100 000 газа заставляло его работать несколько раз).
Я думаю, последствия чего-то подобного в реальном DAO очевидны. Я (ошибочно) предположил, что если во второй транзакции закончится газ, то вся операция (включая первую транзакцию) будет отменена.
Как было предложено в комментарии eth, я задам конкретный вопрос об этой ситуации — как я могу обнаружить это внутри контракта? Поможет ли изменение порядка операций?
Вся операция не была отменена, так как источником транзакции в целом было предоставлено достаточно газа. Если было предоставлено недостаточно газа, вы бы наблюдали ожидаемое поведение, при котором обе внутренние транзакции будут отменены.
Вторая внутренняя транзакция была отменена, так как у нее закончился газ. Чтобы обнаружить это, вызываемая функция может включать true
возвращаемое значение (при необходимости используйте кортеж). Вызывающий может явно проверить это true
значение, потому что при отсутствии газа будет возвращено значение по умолчанию, равное 0 ( false
).
Вот пример того, что произошло. Первая (внутренняя) транзакция требует 200 газа, а вторая транзакция требует 700 газа. Общая сделка была обеспечена 1000 газа. Газ, который был предоставлен второй транзакции, был меньше 700. Весь газ не был полностью предоставлен второй внутренней транзакции. См. нижнее ПРИМЕЧАНИЕ для объяснения.
Вот некоторые вещи, которые могут помочь:
.gas(amount)
синтаксис. Это может затем позволить второй транзакции больше газа. (В приведенном выше примере можно было бы явно ограничить первую внутреннюю транзакцию до 220 единиц газа, так что возмещаемый объем составляет только 20 единиц газа.)Самое простое решение состоит в том , чтобы источник транзакции предоставил больше газа в транзакции . Недостаток небольшой, поскольку весь неиспользованный газ будет возмещен, а при наличии большого количества газа, потенциально доступного для внутренних транзакций, можно избежать крайних случаев.
ПРИМЕЧАНИЕ , почему «весь» газ не предоставляется на вызов (внутренняя транзакция):
chriseth (автор Solidity) сказал :
Это одно из причудливых мест EVM. Вы не можете просто сказать «пришлите весь мой газ вместе со звонком», вы всегда должны указывать явный номер. У нас есть код операции GAS, который дает нам доступное количество газа, но проблема в том, что выполнение самого вызова также требует некоторого количества газа, поэтому мы должны вычесть количество газа, которое стоит вызов, из значения, предоставленного GAS, и мы также должны вычесть количество газа, необходимое для выполнения вычитания...
РЕДАКТИРОВАТЬ: Чтобы прояснить возможные неправильные толкования 1) контракты никогда не платят за газ - они могут резервировать/делегировать/ограничивать газ для другого вызова контракта. 2) Отмененные транзакции по-прежнему включаются в блоки и платный газ.
эт