solidity 语言安全·整型溢出

Netkiller Blockchain 手札

Mr. Neo Chan, 陈景峯(BG7NYT)

中国广东省深圳市龙华新区民治街道溪山美地 518131 +86 13113668890 <netkiller@msn.com>

文档始创于2018-02-10

版权 © 2018 Netkiller(Neo Chan). All rights reserved.

版权声明

转载请与作者联系,转载时请务必标明文章原始出处和作者信息及本声明。

内容摘要

这一部关于区块链开发及运维的电子书。

为什么会写区块链电子书?因为2018年是区块链年,区块链是一个风口,前几个风口我都错过了。例如web2.0, 云, 大数据等等,都从身旁擦肩而过。所以我要抓住这次。

这本电子书是否会出版(纸质图书)? 不会,因为互联网技术更迭太快,纸质书籍的内容无法实时更新,一本书动辄百元,很快就成为垃圾,你会发现目前市面的上区块链书籍至少是一年前写的,内容已经过时,很多例子无法正确运行。所以我不会出版,电子书的内容会追逐技术发展,及时跟进软件版本的升级,做到内容最新,至少是主流。

这本电子书与其他区块链书籍有什么不同?市面上大部分区块链书籍都是用2/3去讲区块链原理,只要不到 1/3 的干货,干货不够理论来凑,通篇将理论或是大谈特谈区块链行业,这些内容更多是头脑风暴,展望区块链,均无法落地实施。本书与那些书籍完全不同,不讲理论和原理,面向应用落地,注重例子,均是干货。

写作原则,无法落地的项目作者绝对不会写。凡是写入电子的内容均具备可操作,可落地。

电子书更新频率?每天都会有新内容加入,更新频率最迟不会超过一周,更新内容请关注 https://github.com/netkiller/netkiller.github.io/commits/master

本文采用碎片化写作,原文会不定期更新,请尽量阅读原文 http://www.netkiller.cn/blockchain/index.html

您的打赏是我的写作动力:http://www.netkiller.cn/blockchain/donations.html

接受 ETH 打赏:0x3e827461Cc53ed7c75A29187CfF39629FCAE3661


什么是整型溢出呢?在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)  => 抛出异常

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

3 条评论
登录 后参与评论

相关文章

来自专栏PHP技术

为什么谷歌要执行严格的代码编写规范

原文出处: Mark CC 译文出处:外刊IT评论 本文是《Google是如何做代码审查的?》的续篇 我们在谷歌所做事情中另外一个让我感到异常有效、有用...

3036
来自专栏程序人生 阅读快乐

高级编译器设计与实现(Steven.S.Muchnick).(中文版)

本书是经典的编译器著作,与“龙书”齐名。书中针对现代语言和体系结构全面介绍了编译器设计与实现的高级论题,从编译器的基础领域中的高级问题开始,然后深入讨论了各种重...

321
来自专栏一块探索区块链

基于Java语言构建区块链(一)—— 基本原型

区块链技术是一项比人工智能更具革命性的技术,人工智能只是提高了人类的生产力,而区块链则将改变人类社会的生产关系,它将会颠覆我们人类社会现有的协作方式。了解和掌握...

5215
来自专栏云加新鲜事儿

跟鹅厂老司机学技术之一:“遇见” Kotlin

6月8日,腾讯云技术社区继续推出了【跟鹅厂老司机学技术】系列分享的第一期:“遇见”Kotlin,邀请到的嘉宾是腾讯工程师霍丙乾。 [1496977258982_...

34310
来自专栏腾讯移动品质中心TMQ的专栏

小样邂逅单元测试后的反思

本文首先从理论层面对单测进行理解,包括澄清自己对单测的误解以及解惑单测的意义(既然要开搞,必须要真正认同并系统认识它);接着结合自己的实际工作,阐述了单测是如何...

1.3K1
来自专栏owent

程序员修炼之道 -- 阅读笔记

终于要离开学校了,终于有时间可以静下来看看之前导师推荐的书籍。之前有看到说《程序员修炼之道》是对程序员影响最为深刻的书, 就从它开始吧。用这个还算可以的音响听...

742
来自专栏CSDN技术头条

必读|提高代码阅读能力的七种实用方法

随着越来越多的公司使用敏捷开发,能够阅读别人的代码比以往显得更重要。这就需要学习一些如何提高这项技能的技巧。本文提供了7种提高代码阅读技巧的方法,以下是译文。 ...

1868
来自专栏区块链入门

【链安科技】EOS智能合约存在溢出漏洞可能

2018年4月28日,成都链安科技向巴比特透露,其研发的面向区块链形式化验证平台VaaS(Verification as a Service)检测发现,基于EO...

754
来自专栏IT派

7 月编程语言指数榜:Python 与 Java 逐渐拉开差距

PYPL 已发布7月编程语言指数榜,Python 在今年5月首次超越 Java 拿下榜首位置后,保持上涨趋势,正逐渐与 Java 拉开差距。

481
来自专栏潘嘉兴的专栏

浅谈知乎是怎么把 SEO 排名做起来的!现在国内最火的问答社区

相信各位都对知乎存在着不解! 知乎到底如何将SEO优化起来了,下面我们来对知乎的SEO进行解答。1.结构好A.每个问题上面都有相关标签,以本问题为例,我们可以看...

1940

扫码关注云+社区