• Solidity拓展:数学运算过程中数据长度溢出的问题


    在数学运算过程中假如超过了长度则值会变成该类型的最小值,如果小于了该长度则变成最大值

    • 数据上溢
    1. uint8 numA = 255;
    2. numA++;

     uint8的定义域为[0,255],现在numA已经到顶了,numA++会使num变成0(由于256已经超过定义域,它会越过256,变成0),即数据发生上溢(越过上边界,叫上溢)。255 --> 256 -->0 上溢。

    • 数据下溢
    1. uint8 numB = 0;
    2. numB--;

    numB本身是低水位线,现在numB-- 会使num变成255(由于-1已经超过定义域,所以它会越过-1,变成255),即数据发生下溢(越过下边界,叫下溢)。0–> -1 --> 255 下溢。  

     可以通过引用 OpenZeppelin的 SafeMath v2.5.x 库,或者自定义一个SafeMath合约,来避免该问题。
        库是 Solidity 中一种特殊的合约,它给原始数据类型增加了一些方法: add(), sub(), mul(), 以及 div()。
        先引用或者import SafeMath库,然后声明 using SafeMath for uint256 ,再通过变量名来调用这些方法。
     

    方法1:

    导入库import "SafeMath"  

    给变量使用库 using SafeMath for 变量类型

    传递参数给库中add函数

    uint e=255;

    e=参数1.add(参数2)           底层是 参数1传给a,参数2传给b 

    方法2:

    也可以自己创建一个库,用library声明,而不是contract

    library SafeMath {

    func add(uint8 a,uint b) internal pure returns(uint 8){ 检验加法

           uint8 = a+b;

           assert(c>=a);

           assert()函数可以用来判断参数是否成立,若不成立则弹出一个错误

           return c;}}

    试例

    1. import "./safemath.sol"; //1)引用库
    2. using SafeMath for uint256; //2)声明指定的类型
    3. uint256 a = 5;
    4. uint256 b = a.add(3); // 5 + 3 = 8 //3)用变量名来调用方法
    5. uint256 c = a.mul(2); // 5 * 2 = 10

    库合约源码

    1. pragma solidity ^0.4.18;
    2. /**
    3. * @title SafeMath
    4. * @dev Math operations with safety checks that throw on error
    5. */
    6. library SafeMath {
    7. /**
    8. * @dev Multiplies two numbers, throws on overflow.
    9. */
    10. function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    11. if (a == 0) {
    12. return 0;
    13. }
    14. uint256 c = a * b;
    15. assert(c / a == b);
    16. return c;
    17. }
    18. /**
    19. * @dev Integer division of two numbers, truncating the quotient.
    20. */
    21. function div(uint256 a, uint256 b) internal pure returns (uint256) {
    22. // assert(b > 0); // Solidity automatically throws when dividing by 0
    23. uint256 c = a / b;
    24. // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    25. return c;
    26. }
    27. /**
    28. * @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
    29. */
    30. function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    31. assert(b <= a);
    32. return a - b;
    33. }
    34. /**
    35. * @dev Adds two numbers, throws on overflow.
    36. */
    37. function add(uint256 a, uint256 b) internal pure returns (uint256) {
    38. uint256 c = a + b;
    39. assert(c >= a);
    40. return c;
    41. }
    42. }
    43. /**
    44. * @title SafeMath32
    45. * @dev SafeMath library implemented for uint32
    46. */
    47. library SafeMath32 {
    48. function mul(uint32 a, uint32 b) internal pure returns (uint32) {
    49. if (a == 0) {
    50. return 0;
    51. }
    52. uint32 c = a * b;
    53. assert(c / a == b);
    54. return c;
    55. }
    56. function div(uint32 a, uint32 b) internal pure returns (uint32) {
    57. // assert(b > 0); // Solidity automatically throws when dividing by 0
    58. uint32 c = a / b;
    59. // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    60. return c;
    61. }
    62. function sub(uint32 a, uint32 b) internal pure returns (uint32) {
    63. assert(b <= a);
    64. return a - b;
    65. }
    66. function add(uint32 a, uint32 b) internal pure returns (uint32) {
    67. uint32 c = a + b;
    68. assert(c >= a);
    69. return c;
    70. }
    71. }
    72. /**
    73. * @title SafeMath16
    74. * @dev SafeMath library implemented for uint16
    75. */
    76. library SafeMath16 {
    77. function mul(uint16 a, uint16 b) internal pure returns (uint16) {
    78. if (a == 0) {
    79. return 0;
    80. }
    81. uint16 c = a * b;
    82. assert(c / a == b);
    83. return c;
    84. }
    85. function div(uint16 a, uint16 b) internal pure returns (uint16) {
    86. // assert(b > 0); // Solidity automatically throws when dividing by 0
    87. uint16 c = a / b;
    88. // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    89. return c;
    90. }
    91. function sub(uint16 a, uint16 b) internal pure returns (uint16) {
    92. assert(b <= a);
    93. return a - b;
    94. }
    95. function add(uint16 a, uint16 b) internal pure returns (uint16) {
    96. uint16 c = a + b;
    97. assert(c >= a);
    98. return c;
    99. }
    100. }
    101. library SafeMath8 {
    102. function mul(uint8 a, uint8 b) internal pure returns (uint8) {
    103. if (a == 0) {
    104. return 0;
    105. }
    106. uint8 c = a * b;
    107. assert(c / a == b);
    108. return c;
    109. }
    110. function div(uint8 a, uint8 b) internal pure returns (uint8) {
    111. // assert(b > 0); // Solidity automatically throws when dividing by 0
    112. uint8 c = a / b;
    113. // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    114. return c;
    115. }
    116. function sub(uint8 a, uint8 b) internal pure returns (uint8) {
    117. assert(b <= a);
    118. return a - b;
    119. }
    120. function add(uint8 a, uint8 b) internal pure returns (uint8) {
    121. uint8 c = a + b;
    122. assert(c >= a);
    123. return c;
    124. }
    125. }

    1.自增修改

    简单变量

    1. uint numA;
    2. numA++;

    优化后 

    1. import "./safemath.sol";
    2. using SafeMath for uint256;
    3. uint numA;
    4. //numA++;
    5. numA = numA.add(1);

    map

    1. mapping(address => uint) ownerAppleCount;
    2. ownerAppleCount[msg.sender]++;

    优化后 

    1. import "./safemath.sol";
    2. using SafeMath for uint256;
    3. mapping(address => uint) ownerAppleCount;
    4. //ownerAppleCount[msg.sender]++;
    5. ownerAppleCount[msg.sender] = ownerAppleCount[msg.sender].add(1);

    结构体 

    1. struct Apple {
    2. uint32 id;
    3. uint weight;
    4. string color;
    5. }
    6. Apple zhaoApple = Apple(100,150,"red");
    7. zhaoApple.weight++;

    优化后 

    1. import "./safemath.sol";
    2. using SafeMath for uint256;
    3. using SafeMath32 for uint32;
    4. struct Apple {
    5. uint32 id;
    6. uint weight;
    7. string color;
    8. }
    9. Apple zhaoApple = Apple(100,150,"red");
    10. //zhaoApple.weight++;
    11. zhaoApple.weight = zhaoApple.weight.add(1);

    2.自减修改

    简单变量

    1. uint8 numB;
    2. numB--;

    优化后 

    1. import "./safemath.sol";
    2. using SafeMath8 for uint8;
    3. uint8 numB;
    4. //numB--;
    5. numB = numB.sub(1);
  • 相关阅读:
    JavaScript基础(11)_方法、枚举对象中的属性、作用域
    python打印 100 以内的素数
    【树莓派开发日记1】1.3k预算的树莓派+显示屏+键鼠的选型与拆箱物理安装
    LeetCode简单题之判断两个事件是否存在冲突
    查找算法——插值查找法
    【漏洞复现】云时空社会化商业ERP系统LoginName SQL注入漏洞
    SpringBoot简介
    基于注解实现缓存的框架 -- SpringCache
    Tomcat 线程模型&性能调优
    猿创征文 |【C++】面向对象之微观部分——类的组成(上)
  • 原文地址:https://blog.csdn.net/weixin_62421736/article/details/130901794