Почему выходные данные смарт-контракта отличаются от обычных транзакций?

Инженер биржи Coinbase сказал:

«Вносить депозиты из смарт-контрактов сложно. Выводы смарт-контрактов не похожи на обычные транзакции ETH, и для нас нетривиально получать уведомления, когда мы получаем монеты из смарт-контрактов».

Точно так же биржа Bitfinex говорит:

«В настоящее время Bitfinex не поддерживает транзакции Ethereum, сгенерированные из смарт-контрактов. Во избежание пропущенных депозитов или задержек с депозитами ETH следует отправлять только в традиционных транзакциях. Если вы не уверены, что ваш депозит не будет отправлен в рамках исполнения контракта Ethereum, пожалуйста, узнайте наверняка перед отправкой депозита».

В чем техническая разница между транзакциями, генерируемыми смарт-контрактами, и транзакциями, генерируемыми людьми? Почему труднее получить уведомление о получении монеты от смарт-контракта (как биржа будет уведомлена о получении монеты от человека, и как она будет уведомлена о получении монеты от смарт-контракта, и почему это другой)? Что послужило мотивом для выбора этого дизайна разработчиками Ethereum? Куда я могу обратиться, чтобы прочитать более подробную информацию?

Я просмотрел https://github.com/ethereum/go-ethereum/wiki/Contracts-and-Transactions , но не увидел там ответа.

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

Ответы (2)

Вот интуиция. Самая простая транзакция в Ethereum стоит 21000 газа и выглядит так :

{from: '0x from', to: '0x to', value: web3.toWei(1, "ether")}

Когда вы вносите депозит toна биржу, биржа может отслеживать транзакции, которые отправляются на toэтот депозитный адрес. Например, для блока 99 они могут использовать web3.eth.getBlock(99, true, ...), и для каждого объекта транзакции проверять, toсовпадает ли адрес депозита и value(количество эфира в wei), которое было отправлено. Относительно просто для обмена, чтобы увидеть, что вы депонировали.

Но если вы используете контракт для внесения депозита, toэто уже не адрес депозита, который вам предоставила биржа. Это toадрес вашего контракта, а в транзакции будет дополнительное dataполе. Это dataдает инструкции контракту для выполнения кода, который затем может перевести эфир на адрес депозита. Биржа также должна исполнить код, если хочет быть уверенной, что получила средства от такого исполнения. (Биржа может использовать web3.eth.getBalance для мониторинга остатков депозитных адресов, но если она хочет точно знать, откуда пришли средства, она должна выполнить код всех транзакций.)

Это обзор, и чтобы узнать больше, в Ethereum Wiki есть ссылки на другие материалы, такие как Yellow Paper и White Paper. Чтение этого StackExchange для вопросов и ответов, получивших большое количество голосов, с такими тегами, как и , также полезно.

Технически транзакции инициируются только людьми: контракт, вызывающий другой контракт, является message call(как определено в «Желтой книге») не транзакцией. В цепочке блоков записывается только транзакция, потому что все дальнейшее выполнение может быть получено из транзакции.


Почему вывод средств с биржи на контрактный кошелек/счет не является простым, потому что требуется больше газа, чем базовый газ 21000. Разные контракты могут потреблять разное количество газа, и биржа должна предоставить достаточное количество газа, иначе транзакция не вступит в силу: оставшиеся средства останутся у биржи.

Извините, если повторяю то, что вы написали, но мне нужно, чтобы вы подтвердили правильность того, что я понял из вашего поста. поэтому, как только эфир переводится из контракта на счет, вам нужно воспроизвести все из начальной транзакции, которая вызвала контракт, чтобы определить окончательный баланс счета, потому что контракты не имеют состояния в сети, только транзакции имеют его? Это правильно?
@NicolasMassart Комментарий немного неясен, но я стараюсь. Контракты имеют состояние. Но в качестве биржи вам нужно воспроизвести или выполнить транзакции, чтобы узнать, по какому контракту были депонированы средства. Контракт может записывать, какие счета он оплатил, но при обмене вы не знаете, какие контракты это делают и как получить доступ к состоянию такого контракта. Там userAccount->контракт->возможно много других контрактов->биржевой депозитный адрес. Что касается обмена, то вы знаете только о самом последнем пункте.
Думаю, я до сих пор не понимаю, зачем обменнику знать, откуда поступает депозит. Мне кажется, проверки web3.eth.getBalance должно быть достаточно. Возможно, вычислительная стоимость запуска web3.eth.getBalance один раз для каждого депозитного адреса, каждого блока больше, чем вычислительная стоимость сравнения каждого депозитного адреса с каждой транзакцией? Но с чего бы это?

В Эфириуме есть два способа отправки средств:

Обычная транзакция: часть данных, подписанная внешним субъектом. Он представляет либо сообщение, либо новый автономный объект. Транзакции записываются в каждый блок блокчейна.

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

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

Это означает, что внутренняя транзакция — это данные и количество эфира, которые передаются между двумя учетными записями. Внутренняя транзакция создается контрактами, взаимодействующими друг с другом, или транзакцией.

Контракт может только отправлять внутреннюю транзакцию.

Некоторые кошельки Exchange способны принимать только обычные транзакции. НЕ ОТПРАВЛЯЙТЕ средства со смарт-контракта на тех. Программное обеспечение биржи, взаимодействующее с адресом кошелька, не будет принимать внутренние транзакции.