原文地址: https://ethereum.stackexchange.com/questions/19341/address-send-vs-address-transfer-best-practice-usage

address.transfer()

  • throws on failure
  • forwards 2,300 gas stipend (not adjustable), safe against reentrancy
  • should be used in most cases as it's the safest way to send ether

address.send()

  • returns false on failure
  • forwards 2,300 gas stipend (not adjustable), safe against reentrancy
  • should be used in rare cases when you want to handle failure in the contract

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

  • returns false on failure
  • forwards all available gas (adjustable), not safe against reentrancy
  • should be used when you need to control how much gas to forward when sending ether or to call a function of another contract

Detailed version below:

The relative tradeoffs between the use of someAddress.send(), someAddress.transfer(), and someAddress.call.value()():

  • someAddress.send()and someAddress.transfer() are considered safe against reentrancy. While these methods still trigger code execution, the called contract is only given a stipend of 2,300 gas which is currently only enough to log an event.
  • x.transfer(y) is equivalent to require(x.send(y)), it will automatically revert if the send fails.
  • someAddress.call.value(y)() will send the provided ether and trigger code execution. The executed code is given all available gas for execution making this type of value transfer unsafe against reentrancy.

Using send() or transfer() will prevent reentrancy but it does so at the cost of being incompatible with any contract whose fallback function requires more than 2,300 gas. It is also possible to use someAddress.call.value(ethAmount).gas(gasAmount)() to forward a custom amount of gas.

One pattern that attempts to balance this trade-off is to implement both a push and pull mechanism, using send() or transfer() for the push component and call.value()() for the pull component.

It is worth pointing out that exclusive use of send() or transfer() for value transfers does not itself make a contract safe against reentrancy but only makes those specific value transfers safe against reentrancy.

More details are here https://consensys.github.io/smart-contract-best-practices/recommendations/#be-aware-of-the-tradeoffs-between-send-transfer-and-callvalue

Reasons for adding transfer(): https://github.com/ethereum/solidity/issues/610


call() can also be used to issue a low-level CALL opcode to make a message call to another contract:

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

The forwarded value and gas can be customized:

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

This is equivalent to using a function call on a contract:

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

Beware of the right padding of the input data in call()https://github.com/ethereum/solidity/issues/2884


transfer(), send() and call() functions are translated by the Solidity compiler into the CALLopcode.

As explained on the Subtleties page in Ethereum's wiki:

CALL has a multi-part gas cost:

  • 700 base
  • 9000 additional if the value is nonzero
  • 25000 additional if the destination account does not yet exist (note: there is a difference between zero-balance and nonexistent!)

Solidity transfer vs send 区别的更多相关文章

  1. read、write 与recv、send区别 gethostname

    recv相对于read有什么区别呢? 其实它跟read函数功能一样,都可以从套接口缓冲区sockfd中取数据到buf,但是recv仅仅只能够用于套接口IO,并不能用于文件IO以及其它的IO,而read ...

  2. 页面跳转Transfer与Redirect的区别你知道吗?

    一 前言 关于页面跳转的方式常用的应该就是,链接跳转,js跳转,Server.Tranfser和Response.Redirect 这几种,可是在Tranfser与Redirect之间用哪种更好(本文 ...

  3. Response.Redirect()、Server.Execute和Server.Transfer的区别

    1.Response.Redirect(): Response.Redirect方法导致浏览器链接到一个指定的URL. 当Response.Redirect()方法被调用时,它会创建一个应答,应答头中 ...

  4. 【转】页面跳转Transfer与Redirect的区别你知道吗?

    一 前言 关于页面跳转的方式常用的应该就是,链接跳转,js跳转,Server.Tranfser和Response.Redirect 这几种,可是在Tranfser与Redirect之间用哪种更好(本文 ...

  5. 页面跳转 Server.Transfer和 Response.Redirect的区别

    1.Server.Transfer 用于把处理的控制权从一个页面转移到另一个页面,在转移的工程中没有离开服务器内部控件(如request,session等)保存的信息不变.因此你能从a页面跳转到b页面 ...

  6. Solidity

    起因是Xenc师傅给我截了张图,我日 居然看不懂 ,一搜才知道,之前学的版本有些老了.. 这次学下新一点的记录下 HelloWorld pragma solidity ^0.6.0; // versi ...

  7. Solidity的三种转账方式与比较

    转账的3种方式 123 address.transfer()address.send()address.call.value().gas()() 转账transfer 12345678910 func ...

  8. java并发:阻塞队列

    第一节 阻塞队列 1.1 初识阻塞队列 队列以一种先进先出的方式管理数据,阻塞队列(BlockingQueue)是一个支持两个附加操作的队列,这两个附加的操作是:在队列为空时,获取元素的线程会等待队列 ...

  9. 10分钟 5步 发布以太坊 ERC20 代币

    1.安装 METAMASK Brings Ethereum to your browser 一个可以浏览器上进行操作的以太坊钱包,推荐 Chrome. Chrome 插件安装地址: https://c ...

随机推荐

  1. 剑指offer-第四章解决面试题思路(字符串的排序)

    题目:输入一个字符串,打印出该字符串的全排列. 思路:将整个字符串分成两部分,第一部分为一个字符,将该字符和该字符后面的字符(直到最后一个字符)依次交换,确定第一个字符:然后固定第一个字符,将后面的字 ...

  2. vim中多行注释和多行删除命令

      1.多行注释:   1. 首先按esc进入命令行模式下,按下Ctrl + v,进入列(也叫区块)模式;   2. 在行首使用上下键选择需要注释的多行;   3. 按下键盘(大写)“I”键,进入插入 ...

  3. HTTP/HTTPS原理详解

    简介 HTTP(Hypertext Transfer Protocal,超文本传输协议)是WWW(World Wide Web,万维网)数据传输的基础,规定如何传输超文本.HTTP协议存在多个版本:H ...

  4. laravel中有条件使用where

    在项目开发的过程中;有时候会有多个参数 去用在where查询中;那么这里的where语句是可能有也可能没有的 1.用原生的mysql语句来实现 private function getData($ty ...

  5. 1056 Mice and Rice

    题意:略 思路:利用queue来模拟一轮一轮的比赛.自己第一遍做的时候完全没有用queue做的意识,代码写的贼烦最后还只得了17分,非常郁闷.通过本题反映出对queue的应用场景季度不熟悉,STL里面 ...

  6. 八 Connect API 连接器

    Connect API: 实现一个连接器(connector),不断地从一些数据源系统拉取数据到kafka,或从kafka推送到宿系统(sink system). 大多数Connect使用者不需要直接 ...

  7. Lagom production deployment

    tutorial:https://developer.lightbend.com/guides/lagom-kubernetes-k8s-deploy-microservices/ 一.harbor ...

  8. PHP函数(二)-不定参数的传递

    如果要传递不定数量的参数,需要使用func_get_args()函数来传递 func_num_args()函数用来返回参数的总数 <?php function more_args(){ $arg ...

  9. 使用airodump-ng扫描网络

    执行命令 root@sch01ar:~# airodump-ng wlan0mon 参数介绍: BSSID:表示无线AP的Mac地址 PWR:网卡报告的信号水平 Beacons:无线AP发出的通告编号 ...

  10. Ansible之Playbooks的when语句

    在使用ansible做自动化运维的时候,大多数情况下都执行某些任务的时候都需要依赖某个变量的值或者是上一个任务的执行结果.如,根据facts信息中的系统版本相关的信息来确定使用哪种包管理器安装软件.A ...