- 第 1 章 区块链
- 第 2 章 以太坊
- 第 3 章 以太坊私链入门
- 第 4 章 以太坊网络
- 第 5 章 geth v1.8.16 命令详解
- 第 6 章 Wallet
- 第 7 章 Token
- 第 8 章 智能合约语言 Solidity v0.5.0
- 第 9 章 Truffle v4.1.8 开发框架
- 第 10 章 web3.js - 1.0.0
- 第 11 章 web3j v3.4.0 - Jave Client
- 11.2. 启动以太坊
- 11.3. Maven pom.xml 文件
- 11.4. Java 与 Solidity 数据类型映射关系
- 11.5. 常量
- 11.6. 连接到服务器获取版本号
- 11.7. 获得以太坊状态信息
- 11.8. 单位转换
- 11.9. 账号管理
- 11.10. Credentials
- 11.11. 交易
- 11.12. 钱包
- 11.13. 智能合约
- 11.14. ERC20合约
- 11.15. Infura
- 11.16. 助记词
- 11.17. 过滤器 (Filter)
- 11.18. Subscription
- 11.19. 解锁账号
- 11.20. IBAN (International Bank Account Number)
- 11.21. Springboot with Ethereum (web3j)
- 第 12 章 web3.py - A python interface for interacting with the Ethereum blockchain and ecosystem.
- 第 14 章 Ethereum Developer APIs
- 第 15 章 infura
- 第 16 章 以太坊案例
- 第 17 章 FAQ
- 17.3. Error: authentication needed: password or unlock
- 17.4. 新增节点后不生效
- 17.5. Unhandled rejection Error: Returned error: The method personal_unlockAccount does not exist/is not available
- 17.6. Error: exceeds block gas limit
- 17.7. Migrations.sol:11:3: Warning: Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(…) { … }" instead.
- 17.8. Exception in thread "main" rx.exceptions.OnErrorNotImplementedException: Invalid response received: okhttp3.internal.http.RealResponseBody@6c25e6c4
- 17.9. 旧版本 Remix(browser-solidity) 本地安装
- 第 18 章 Hyperledger Fabric v2.0.0
- 第 19 章 Hyperledger Fabric 运维
- 第 20 章 Chaincode 链码(智能合约)
- 第 21 章 Hyperledger Fabric Client SDK for Node.js
- 第 22 章 fabric-sdk-java
- 第 24 章 已知 Hyperledger 落地案例
- 第 25 章 Fabric Command
- 第 26 章 Fabric FAQ
- 第 27 章 IPFS(InterPlanetary File System,星际文件系统)
- 第 28 章 IPFS 命令
- 第 29 章 IPFS WebUI
- 第 30 章 IPFS 集群配置
- 第 31 章 IPFS API
- 第 32 章 IPFS Faq
- 第 33 章 EOS
- 第 34 章 EOS 安装
- 第 35 章 CLEOS
- 第 36 章 智能合约开发
- 第 37 章 EOS Dapp 开发
- 第 38 章 FAQ
- 第 39 章 BaaS (Blockchain as a Service) 平台
- 第 40 章 BitCoin
- 第 41 章 其他区块链相关
- 附录 1. 附录
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
8.15. Solidity 安全问题
8.15. Solidity 安全问题
8.15.1. 整型溢出
什么是整型溢出呢?在solidity编写合约时,定义整型一般是用uint8, uint256。一个变量如果定义为uint8表示的无符号的8位整型,即取值范围为0-255。当给这个变量赋值256时,即整型溢出变成了0,以此类推257变成了1。
pragma solidity ^0.4.24; //author: netkiller <netkiller@msn.com> //homepage: http://www.netkiller.cn contract NetkillerOverflowTest{ function add(uint8 a, uint8 b) pure public returns (uint8){ uint8 result = a + b; return result; } function sub(uint8 a, uint8 b) pure public returns (uint8){ uint8 result = a - b; return result; } function mul(uint8 a, uint8 b) pure public returns (uint8){ uint8 result = a * b; return result; } function div(uint8 a, uint8 b) pure public returns (uint8){ uint8 result = a / b; return result; } }
调用上面合约,运行结果
254 + 1 = 255 254 + 2 = 0 254 + 3 = 1
减法运行结果
10 - 20 = 246
乘法运行结果
51 * 5 = 255 51 * 6 = 50
再来测试乘法
255 / 10 = 25
这有点想千年虫问题,即99年变成00年后,你无法区分1900年还是2000年。
现在测试一下uint256,uint256支持的取值范围是0到2^256-1
pragma solidity ^0.4.24; //author: netkiller <netkiller@msn.com> //homepage: http://www.netkiller.cn contract TestUint256Overflow { // (2**256 – 1) + 1 = 0 向上溢出测试 function overflow() pure public returns (uint256 _overflow) { uint256 max = 2 ** 256 - 1; return max + 1; } // 0 – 1 = 2**256 – 1 向下溢出测试 function underflow() pure public returns (uint256 _underflow) { uint256 min = 0; return min - 1; } }
运行结果
_overflow : 0 _underflow : 115792089237316195423570985008687907853269984665640564039457584007913129639935
第一个函数溢出为 0,第二个函数 0 - 1 = 115792089237316195423570985008687907853269984665640564039457584007913129639935
解决溢出问题使用SafeMath库
pragma solidity ^0.4.24; //author: netkiller <netkiller@msn.com> //homepage: http://www.netkiller.cn library SafeMath { function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { if (a == 0) { return 0; } c = a * b; assert(c / a == b); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } function add(uint256 a, uint256 b) internal pure returns (uint256 c) { c = a + b; assert(c >= a); return c; } } contract NetkillerSafeMath { using SafeMath for uint256; function add(uint256 a, uint256 b) pure public returns (uint256){ uint256 result = a.add(b); return result; } function sub(uint256 a, uint256 b) pure public returns (uint256){ uint256 result = a.sub(b); return result; } function mul(uint256 a, uint256 b) pure public returns (uint256){ uint256 result = a.mul(b); return result; } function div(uint256 a, uint256 b) pure public returns (uint256){ uint256 result = a.div(b); return result; } }
测试 SafeMath
add(115792089237316195423570985008687907853269984665640564039457584007913129639934,1) => 115792089237316195423570985008687907853269984665640564039457584007913129639935 add(115792089237316195423570985008687907853269984665640564039457584007913129639935,1) => 抛出异常
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论