<address> .send vs <address & gt ;.переключение наилучшей практики использования;

Я заметил, что адрес предлагает две функции-члены, которые выполняют передачу эфира по указанному адресу. send возвращает false при ошибке и transfer вызывает исключение. В документации Solidity приведен пример, который использует оба вызова Простой открытый аукцион .

Когда мне следует использовать send и когда мне следует использовать transfer?

33 голоса | спросил Michael 4 J000000Tuesday17 2017, 00:16:11

2 ответа


22

Оба send и transfer считаются безопасным способом перемещения средств, поскольку у них есть газовая стипендия в размере 2300.

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

ответил Jakub Wojciechowski 4 J000000Tuesday17 2017, 00:46:28
38

address.transfer()

  • срабатывает
  • форварды 2,300 газовая стипендия (не регулируемая), защищенная от повторного размещения
  • следует использовать в большинстве случаев, так как это самый безопасный способ отправки эфира.

address.send()

  • возвращает false при ошибке
  • форварды 2,300 газовая стипендия (не регулируемая), защищенная от повторного размещения
  • следует использовать в редких случаях, когда вы хотите обработать сбой в контракте

address.call.value().gas()()

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

Подробная версия ниже:

Относительные компромиссы между использованием someAddress.send(), someAddress.transfer() и someAddress.call.value()()

  • someAddress.send() и someAddress.transfer() считаются безопасными для повторного размещения. Хотя эти методы по-прежнему вызывают выполнение кода, в названном контракте предоставляется только стипендия в 2300 га, что в настоящее время достаточно для регистрации события.
  • x.transfer(y) эквивалентен require(x.send(y)), он автоматически вернется, если сбой не удался.
  • someAddress.call.value(y)() отправит предоставленный эфир и запуск кода запуска. Выполненному коду предоставляется весь доступный газ для выполнения, делая этот тип переноса стоимости небезопасным по сравнению с повторным размещением.

Использование send() или transfer() предотвратит повторное размещение, но это произойдет за счет того, что он несовместим с любым контрактом, для возврата которого требуется более 2300 газов. Также можно использовать someAddress.call.value(ethAmount).gas(gasAmount)() для отправки пользовательского количества газа.

Один шаблон, который пытается сбалансировать этот компромисс, заключается в реализации как push и pull , используя send() или transfer() для push-компонента и call.value()() для компонента pull.

Стоит отметить, что эксклюзивное использование send() или transfer() для переноса значений само по себе не делает договор безопасным для повторного использования, но только делает эти конкретные перенос ценностей безопасен против повторного размещения.

Подробнее здесь https://consensys.github.io/smart-contract-best-practices/recommendations/#be-aware-of-the-tradeoffs-between-send-transfer-and-callvalue

Причины добавления transfer(): https: //github .com /Эфириум /монолитность /вопросы /610


call() также может использоваться для выдачи кода кода низкого уровня CALL для вызова сообщения другому контракту:

if (!contractAddress.call(bytes4(keccak256("someFunc(bool, uint256)")), true, 3)) {
    revert;
}

Переадресованное значение value и gas можно настроить:

contractAddress.call.gas(5000)
    .value(1000)(bytes4(keccak256("someFunc(bool, uint256)")), true, 3);

Это эквивалентно использованию вызова функции по контракту:

SomeContract(contractAddress).someFunc.gas(5000)
    .value(1000)(true, 3);

Остерегайтесь правильного заполнения входных данных в call() https://github.com/ethereum/solidity/issues/2884


Функции

transfer(), send() и call() преобразуются компилятором Solidity в CALL opcode.

Как пояснялось на странице Subtleties в вики-файле Ethereum:

  

CALL имеет цену на несколько частей:

     
  • 700 base
  •   
  • 9000 дополнительных, если значение отличное от нуля
  •   
  • 25000 дополнительных, еслицелевая учетная запись еще не существует (обратите внимание: существует разница между нулевым балансом и несуществующим!)
  •   

Детское сообщение нецелесообразной операции CALL (НЕ сообщение верхнего уровня, возникающее из транзакции!) получает дополнительно 2300 газа поверх газа, подаваемого вызывающим счетом; эта стипендия может считаться выплаченной из 9000 обязательных дополнительных сборов за звонки с ненулевой стоимостью. Это гарантирует, что получатель звонка всегда будет иметь достаточно газа для регистрации, что он получил средства.


Отправка и получение эфира объясняется в Solidity docs :

ответил medvedev1088 5 FebruaryEurope/MoscowbMon, 05 Feb 2018 22:34:45 +0300000000pmMon, 05 Feb 2018 22:34:45 +030018 2018, 22:34:45

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132