Может кто-нибудь объяснить разницу между использованием отправки и вызова для контрактов, а также когда использовать и не использовать эти разные методы?
Например :
msg.sender.send(number);
msg.sender.call.value(number)();
Я знаю, что для отправки используется газ 2300, а для вызова не используется газ.
РЕДАКТИРОВАТЬ, декабрь 2019 г.: call.value()()
теперь следует использовать для передачи эфира. (Не используйте функцию отправки или передачи.)
См.: Является ли transfer() безопасным после обновления Istanbul?
1 Send()
больше не подает газ. Он просто использует жестко закодированную стипендию (2300 газа), полученную из стоимости передачи стоимости (минимум 9040). Этого достаточно, чтобы отправить эфир, но также достаточно, чтобы выполнить одну дополнительную небольшую операцию регистрации (в резервной функции). Следующие операции будут потреблять больше газа, чем стипендия, предоставляемая резервной функции:
• Запись в хранилище
• Создание контракта
• Вызов внешней функции, потребляющей большое количество газа
• Отправка эфира
2 Если у send()
вызова заканчивается газ, он не выдает ошибку, он просто возвращает false.
из Solidity Doc:
Если контракт получает эфир (без вызова функции), выполняется резервная функция. Контракт может полагаться только на «газовую стипендию» (2300 газа), доступную ему в то время. Этой стипендии недостаточно, чтобы каким-либо образом получить доступ к хранилищу. Чтобы убедиться, что ваш контракт может получать эфир таким образом, проверьте требования к газу для резервной функции (например, в разделе «Подробности» в браузере-солидности).
• Существует способ направить больше газа принимающему контракту с помощью addr.call.value(x)(). По сути, это то же самое, что и addr.send(x), только перенаправляет весь оставшийся газ и открывает получателю возможность выполнять более дорогостоящие действия. Это может включать обратный вызов контракта отправки или другие изменения состояния, о которых вы могли не знать. Таким образом, это обеспечивает большую гибкость как для честных пользователей, так и для злоумышленников.
Предупреждение : Контракты, которые получают эфир, но не определяют резервную функцию, вызывают исключение, отправляя эфир обратно (до версии Solidity v0.4.0 это было по-другому). Поэтому, если вы хотите, чтобы ваш контракт получал эфир, вы должны реализовать резервную функцию.
.call()
. И не могу не подчеркнуть, что .call()
«обеспечивает большую гибкость как для честных пользователей, так и для злоумышленников».2,300
газовую стипендию, защищенную от повторного входаfalse
в случае неудачи2,300
газовую стипендию, защищенную от повторного входаfalse
в случае неудачиВы можете прочитать более подробную информацию здесь https://ethereum.stackexchange.com/a/38642/18932
Алекс Дарби
эт
.call
не создает транзакцию; только что написал это, в котором есть другие детали, которые вы, возможно, ищете: ethereum.stackexchange.com/a/6477/42Тьяден Хесс
send
посылает больше, чем 0 газа, не так ли? Отправляет 23000эт
send
отправляет 0 газа, но есть правило EVM, согласно которому получатель всегда получает стипендию в размере 2300 газа (так что, если он захочет, у него всегда будет достаточно газа, чтобы зарегистрировать, что он что-то получил).Ксавье Лепретр B9lab
.call
Javascript (без транзакции) с.call
Solidity (уже в транзакции).Алекс Дарби