Как избежать/обнаружить множественные побочные эффекты отсутствия газа во внутренних транзакциях?

После проблемы, которую я открыл в github, это меня беспокоит. Операция, описанная в проблеме, которая произошла во время следующего руководства avsa по созданию DAO, сгенерировала две внутренние транзакции, как видно здесь: TXВкратце, внутренние транзакции:

  • Изменить статус запрошенной операции в DAO на «завершено»
  • Фактически выполнить операцию, отправив транзакцию в другой контракт

Первая внутренняя транзакция завершена успешно — это означает обновление операции в DAO до статуса «завершено». Второй терпит неудачу, скорее всего, потому, что у него закончился газ (несколько попыток дали одинаковые результаты, а добавление 100 000 газа заставляло его работать несколько раз).

Я думаю, последствия чего-то подобного в реальном DAO очевидны. Я (ошибочно) предположил, что если во второй транзакции закончится газ, то вся операция (включая первую транзакцию) будет отменена.

Как было предложено в комментарии eth, я задам конкретный вопрос об этой ситуации — как я могу обнаружить это внутри контракта? Поможет ли изменение порядка операций?

Спасибо за ваш первый вопрос, и у него есть задатки довольно хороший. Вопросы и ответы должны иметь возможность стоять сами по себе, без необходимости нажимать на ссылки (потому что ссылки становятся мертвыми). В связи с этим предлагаю пересмотреть. Ваш вопрос также состоит из нескольких частей, и его разделение может быть лучше. Вопрос 1 об изменении порядка специфичен для вашего примера, но остальные можно задавать отдельно.

Ответы (1)

Вся операция не была отменена, так как источником транзакции в целом было предоставлено достаточно газа. Если было предоставлено недостаточно газа, вы бы наблюдали ожидаемое поведение, при котором обе внутренние транзакции будут отменены.

Вторая внутренняя транзакция была отменена, так как у нее закончился газ. Чтобы обнаружить это, вызываемая функция может включать trueвозвращаемое значение (при необходимости используйте кортеж). Вызывающий может явно проверить это trueзначение, потому что при отсутствии газа будет возвращено значение по умолчанию, равное 0 ( false).

Вот пример того, что произошло. Первая (внутренняя) транзакция требует 200 газа, а вторая транзакция требует 700 газа. Общая сделка была обеспечена 1000 газа. Газ, который был предоставлен второй транзакции, был меньше 700. Весь газ не был полностью предоставлен второй внутренней транзакции. См. нижнее ПРИМЕЧАНИЕ для объяснения.

Вот некоторые вещи, которые могут помочь:

  • изменение порядка операций, как вы предлагаете, может помочь, потому что транзакция, в которой закончился газ, теперь будет первой и будет иметь весь доступный газ для начала (вместо того, чтобы требовать возмещения газа)
  • сохраняя операции в том же порядке, но для первой транзакции ограничьте газ, отправляемый с вызовом функции через .gas(amount)синтаксис. Это может затем позволить второй транзакции больше газа. (В приведенном выше примере можно было бы явно ограничить первую внутреннюю транзакцию до 220 единиц газа, так что возмещаемый объем составляет только 20 единиц газа.)

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

ПРИМЕЧАНИЕ , почему «весь» газ не предоставляется на вызов (внутренняя транзакция):

chriseth (автор Solidity) сказал :

Это одно из причудливых мест EVM. Вы не можете просто сказать «пришлите весь мой газ вместе со звонком», вы всегда должны указывать явный номер. У нас есть код операции GAS, который дает нам доступное количество газа, но проблема в том, что выполнение самого вызова также требует некоторого количества газа, поэтому мы должны вычесть количество газа, которое стоит вызов, из значения, предоставленного GAS, и мы также должны вычесть количество газа, необходимое для выполнения вычитания...

РЕДАКТИРОВАТЬ: Чтобы прояснить возможные неправильные толкования 1) контракты никогда не платят за газ - они могут резервировать/делегировать/ограничивать газ для другого вызова контракта. 2) Отмененные транзакции по-прежнему включаются в блоки и платный газ.