Почему мой TX не работает из-за отсутствия газа, хотя было подано правильное количество газа?

Предупреждение: я пытался предоставить ссылки на свои транзакции и адреса в etherscan.io, но мне «нужно не менее 10 репутации, чтобы опубликовать более 2 ссылок».

У меня есть аккаунт, который я хочу проверить. Я хочу перевести ETH в контракт о разделе средств (ETC/ETH). Я заинтересован только в подметании баланса ETH, и моя цель состоит в том, чтобы на счете был нулевой баланс (например, без пыли).

Это контракт о разделении фонда, который я пытаюсь использовать: 0x1e143b2588705dfea63a17f2032ca123df995ce0 .

Кажется, что для этой операции требуется 29 717 газа. Например, вот пример транзакции, которую я отправил на контракт, который согласно etherscan.io требовал такого количества газа :

Однако, если я отправлю транзакцию и ограничу количество газа до 29 717, моя транзакция завершится неудачно. Например, вот пример транзакции, которую я отправил на контракт с лимитом газа 29 717, который не удался из-за отсутствия газа: 0xcd31481b4dd9410daa22c8a47f9a4b29ef4a305877174eb346433bb4e6b03089(TX)

Я обнаружил, что минимальное количество газа, которое мне нужно указать для работы одного из этих переводов, составляет 31 991:

  • Сработала транзакция с 31 991 газом: 0x7cd52325c0945d0de975a6713abdc50659c0c62ef523a1a99f2ad2a2d4128a8f(TX)
  • Неудачная транзакция с 31 990 газами: 0x8c92fde3cf07b3cdbf4dcc54ed6ccfb072f22933ab556612f3d23317a2466280(TX)

Однако, когда tx проходит, кажется, что он использовал только 29 717 газа. Например: Счет 0x19d90f1106c600bd8a70b5775776b4ecdc7a945b(адрес) имел баланс 0.01282711 ETH(в блоке 1964300).

Я отправил транзакцию 0xb57c8b5aede3070e2fb80ea9a21ec43293cb5c7392ccb36357388422e9055509(TX) со следующими данными:

  • Ценность:0.01218729 ETH
  • Газ:31991
  • Цена на газ:20000000000 Wei

Так:

  • Баланс до ТХ:0.01282711 ETH
  • Сумма для отправки:0.01218729 ETH
  • Предполагаемая стоимость ТХ: Gas* Price=0.00063982 ETH
  • Баланс - Сумма для отправки - Предполагаемая стоимость TX = НОЛЬ!

Однако, как вы можете видеть, на счете 0x19d90f1106c600bd8a70b5775776b4ecdc7a945b(адресе) есть баланс 0.00004548 ETH.

Это, в свою очередь, означает, что фактическая стоимость TX была 0.00059434 ETHследующей: Фактическая стоимость TX = Баланс до TX - Отправленная сумма - Фактический конечный баланс = 0,01282711 - 0,01218729 - 0,00004548 = 0,00059434.

При цене газа 20000000000 Wei, это означает, что количество использованного газа составило: 29717(0,00059434/0,00000002 = 29717)

Итак, вопрос:

  1. Почему транзакции, в которых указан лимит газа, 29717терпят неудачу?
  2. Как вывести средства, чтобы конечный баланс учетной записи ETH был равен нулю при использовании вышеуказанного контракта?

Системная информация

Версия Geth: 1.4.10-stable-c2eea630 ОС и версия: Linux

Ожидаемое поведение

Транзакция 0x19d90f1106c600bd8a70b5775776b4ecdc7a945b должна была пройти успешно.

Фактическое поведение

Транзакция 0x19d90f1106c600bd8a70b5775776b4ecdc7a945b завершилась неудачно из-за отсутствия газа.

Шаги для воспроизведения поведения

Используйте transfer(address)функцию контракта 0x1e143b2588705dfea63a17f2032ca123df995ce0, отправив некоторую сумму и ограничив количество газа до29717

Вот пример транзакции для этого контракта, которую вы можете отправить через JSON-RPC API:'{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{"from":"0xe7c7d161800ebb5112d7d892510e9f1dafc4010c","to":"0x1e143b2588705dfea63a17f2032ca123df995ce0","value":"0x1F99A58657EED0","data":"0x1a69523000000000000000000000000029d5527caa78f1946a409fa6acaf14a0a4a0274b"}],"id":6}'

Ответы (1)

Понимание этой головоломки может быть поучительным. Поведение можно объяснить тем, как CALLработает инструкция с точки зрения газа.

Мы можем сравнить трассировки транзакций VM здесь:

(Ссылки на программный счетчик непосредственно перед сбоем CALL).

Рассмотрим обе транзакции параллельно, Aбудет успешная транзакция и Bнеудачная. Значение представляет собой остаточный газ на любом шаге.

  1. Звонок по контракту: A = 31991, B = 29717.
  2. Еще до начала контракта 22680они потребляются. A = 9311, B = 7037.
  3. Выполняется ряд инструкций, совокупная стоимость которых составляет 271.
  4. Таким образом, перед фактической передачей CALLна шаге 65 мы находимся в точке A = 9040, B = 6766.
  5. В этот момент Bпроисходит сбой, потому что у него недостаточно газа для выполнения CALLинструкции, которая стоит 9040 gas.
  6. Однако после звонка 9040 gasони не были полностью израсходованы A: мы вернулись к 2300.
  7. Aпродолжает свою работу до последней инструкции, в которой он находится 2274.
  8. Неиспользованные 2274возмещаются, и общий объем потребляемого газа действительно равен 31991-2274 = 29717.

Есть два момента, которые объясняют удивительное поведение.

  • Стоимость CALL с переводом стоимости составляет 40 + 9000. (согласно приложению G к Yellow Paper ).
  • Из этой стоимости берется 2300 газа и направляется получателю в качестве газа .

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

В нашем случае, поскольку счет получателя не является контрактом, stipendденьги были возвращены. В каком-то смысле CALLстоимость операции была всего лишь 6740 gas, но мы должны были показать, что мы должны по крайней мере 9040покрыть случай контрактного абонента.

В предыдущих версиях весь газ вызывающего абонента перенаправлялся вызываемому, но это было открыто для злоупотреблений, и было введено новое поведение.

Больше ссылок: