原文地址:https://medium.com/@kidinamoto/how-to-send-ether-correctly-a60208ad76d9

Compare send, call & transfer

Let’s see the following code

pragma solidity ^0.4.13;
contract someContract { mapping(address => uint) balances; function deposit() payable {balances[msg.sender] += msg.value; } //VERY very bad below  function withdrawVeryBad1(uint amount) {if(balances[msg.sender] >= amount){msg.sender.send(amount); balances[msg.sender] -= amount; } } 
 function withdrawVeryVeryBad2(uint amount){if(balances[msg.sender] >= amount) { msg.sender.call.gas(2500000).value(amount)(); balances[msg.sender] -= amount; }
}  
function withdrawVeryVeryBad3(uint amount) { if(balances[msg.sender] >= amount) {        if(msg.sender.call.gas(2500000).value(amount)()) {                balances[msg.sender] -= amount; } }
} 
function withdrawBad1(uint amount) { if(balances[msg.sender] >= amount) {
if(msg.sender.send(amount)) {
balances[msg.sender] -= amount; } }
} 
function withdrawOkayish(uint amount) { if(balances[msg.sender] >= amount) { balances[msg.sender] -= amount;    if(!msg.sender.send(amount)) { throw; } } } 
function withdrawBad2(uint amount) { if(balances[msg.sender] >= amount) { balances[msg.sender] -= amount;   if(!msg.sender.call.gas(2500000).value(amount)()) { throw; } }
} 
//OKAY FUNCTIONS
function withdrawOK(uint amount) { if(balances[msg.sender] >= amount) { balances[msg.sender] -= amount;
msg.sender.transfer(amount); }
} 
//New Exception handling
function withdrawGood(uint amount) { require(balances[msg.sender] >= amount); balances[msg.sender] -= amount;msg.sender.transfer(amount); }
}

In the first

function withdrawVeryBad1(uint amount) {if(balances[msg.sender] >= amount){msg.sender.send(amount); balances[msg.sender] -= amount; } }

The problem is that we do not check if the return value of send is false or not. If the msg.sender is a contract, it will runs out of gas(> 2300), then it will return False. But we will still reduce the balance because there is no exception.

function withdrawVeryVeryBad2(uint amount){if(balances[msg.sender] >= amount) { msg.sender.call.gas(2500000).value(amount)(); balances[msg.sender] -= amount; }
}

In this example, we can run call again and again until the contract has no ether left. the stack size is 1024 so we can do it 1024 times. it’s very bad to reduce the balance after send .

function withdrawVeryVeryBad3(uint amount) { if(balances[msg.sender] >= amount) {        if(msg.sender.call.gas(2500000).value(amount)()) {                    balances[msg.sender] -= amount; } }
}

veryverybad3 is also not good because it only use if statement.

function withdrawBad1(uint amount) { if(balances[msg.sender] >= amount) { if(msg.sender.send(amount)) { balances[msg.sender] -= amount; } }
}

if msg.sender is a contract, send will run out of gas. So the function can only work at some rare cases.again, we shouldn’t reduce the balance after.

function withdrawOkayish(uint amount) { if(balances[msg.sender] >= amount) { balances[msg.sender] -= amount;    if(!msg.sender.send(amount)) { throw; } } }

withdrawOkayish is much better, but still not working with re-entrence. the problem is still we are sending 2300 gas.

msg.sender.call.gas(2500000).value(amount)()

does the same as

msg.sender.transfer(amount);

but transfer propagate exceptions.

we can have a require statement instead of if.

require(balances[msg.sender] >= amount);
  • Ethereum

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.

正确地实现以太币转账相关推荐

  1. android web3j 代币查询_使用Web3.js查询以太币和代币余额以及转账

    前言 前面的文章也提到了,使用web3.js可以与以太坊进行互动.这篇文章的主要内容如下:解决web3.js版本问题 2.使用web3.js查询以太币及代币余额,以及进行以太币和代币转账 1.web3 ...

  2. 以太币(Ether)的单位

    原文地址:https://zhuanlan.zhihu.com/p/28994731 以太币(Ether)的单位 李明阳 手持两把锟斤拷,口中疾呼烫烫烫 已关注 71 人赞了该文章 在以太坊(Ethe ...

  3. Python 使用 Web3.py 进行 ETH 和代币转账

    1.安装 Web3.py pip install web3.py 2.注册 Infura 获得节点服务 使用邮箱注册 Infura 账户后,创建一个项目,即可获得以太坊节点服务,进入设置即可看到链接的 ...

  4. 因合约代码Bug,约2.2亿元11539枚以太币被永久锁定

    上周五,一个叫AkuDreams的3D动画NFT项目在荷兰拍卖会上遭遇了Bug惨案,因智能合约代码bug,投标者的 11539.5 枚以太币被永久锁定,且无法退款.该加密货币价值 3400 万美元,约 ...

  5. 以太币转帐速度_燃起来吧!一文带你读懂以太坊网络中的Gas、Gas Fee、Gas Price、Gas...

    曾用过区块链相关应用,不管是交易所.DApp 或是虚拟货币钱包的人,一定都听过矿工费(Gas Fee) 这个词.它是当你要在区块链网路发起一笔交易时,所要支付给矿工的一笔手续费.其实很容易理解,就好比 ...

  6. android web3j 代币查询_ERC20代币转账以及余额查询--java(web3j)

    ERC20代币转账以及余额查询–java(web3j) 准备工作:转账之前你得有一个ERC20代币,代币发行戳这里,可以在测试网上进行测试. 因为发行代币本质就是部署智能合约,是需要消耗gas的,代币 ...

  7. 前端Vue项目调用页面web3.js:连接metaMask钱包,(查询钱包ETH余额,查询代币余额,ETH转账,代币转账,代币授权,查询授权数量,计算价格)等功能

    这里分享下相关文档 1.web3.js中文文档 https://learnblockchain.cn/docs/web3.js/getting-started.html 2.metamask官方文档: ...

  8. 代币转账_手把手教你从源代码开始搭建多节点以太坊私链(五)部署智能合约及代币发行...

    一.安装以太坊合约编译环境 安装solc 智能合约代码的编译可以通过第三方平台或者软件.不过,为了安全起见,还是搭建自己的编译器比较好.(But be aware that if the compil ...

  9. 以太坊转账参数java_【ETH钱包开发04】web3j转账ERC-20 Token

    在上一篇文章中讲解了ETH转账,这一篇讲一下ERC-20 Token转账. [ETH钱包开发03]web3j转账ETH ERC-20 Token转账的2种方式 1.直接用web3j的API 2.jav ...

最新文章

  1. 对话“互联网先驱”:星际互联网究竟可不可行?
  2. 对Web页面元素的绝对唯一引用方法
  3. HTML的dl、dt、dd标记制作表格对决Table制作表
  4. 如何提高SSD的使用寿命
  5. Linux移植遇到问题记录
  6. 使用鸢尾花数据集实现一元逻辑回归、多分类问题
  7. Oracle实例和Oracle数据库(Oracle体系结构)
  8. php云解析播放器,xyplay云解析PHPV3.4.1优化稳定版视频解析
  9. Cordova - 解决升级NDK之后无法编译!
  10. java难度_你们觉得java难吗?
  11. 07: redis分布式锁解决超卖问题
  12. gcd常见结论及gcd与斐波那契结合--hdu6363.
  13. React:组件的生命周期
  14. 前端响应式布局与Bootstrap栅格系统快速了解与应用
  15. PS把模糊的照片变清晰
  16. type c 网卡 外接网卡 禁用后 不见 消失 找不到 的解决办法
  17. 三菱转以太网模块连接 FX3U/3UC系列 PLC使用步骤
  18. 【solr】solr介绍
  19. 脑洞大开!未来学家预测未来变迁,中国将成世界AI培训中心!(附链接)
  20. 一篇不错的项目管理之道

热门文章

  1. treemap怎么保证有序_你对多线程熟悉吗,谈谈线程安全中的原子性,有序性和可见性?...
  2. 算数运算符与关系运算符_Swift进阶三——运算符相关
  3. python列表到元祖_python列表与元祖
  4. 华为python面试题库_我收集了100道Python面试题,开源到了Github
  5. delphi7下实现http的post_ASP.NET Core Web API 实现过程
  6. 想念你 2012-10-24 23:27
  7. SQL SERVER将多行数据合并成一行(转载)
  8. SQL Server 日志数据库清理办法
  9. [CODEVS 1036]商务旅行
  10. VB 泛型 T 应用