區塊鏈技術資源分享
追尋中本聰先生的腳步
?

防止溢出和下溢_智能合約_MOAC BlockChain SafeMath庫@李預清

在編寫智能合約的時候需要注意的一個主要的安全特性:防止溢出和下溢。為了防止這些情況,OpenZeppelin建立了一個叫做SafeMath的庫(library),默認情況下可以防止這些問題。

什么是溢出(overflow)

假設我們有一個uint8, 只能存儲8 bit數據。這意味著我們能存儲的最大數字就是二進制11111111(或者說十進制的2^8-1 =255).

來看看下面的代碼。最后 number 將會是什么值?

什么是溢出(overflow)

在這個例子中,我們導致了溢出---雖然我們加了1,但是number出乎意料地等于0了。

下溢(underflow)也類似,如果你從一個等于0的uint8減去1, 它將變成255 (因為uint是無符號的,其不能等于負數)。

分析 SafeMath源碼

1.加法,僅限內部調用,返回 uint256

require(c>=a && c>=b); //驗證結果: 兩個正數相加,和一定大于每個加數

SafeMath源碼加法

2.減法,僅限內部調用,返回 uint256

require(b <= a) 因為返回值需要是 正數,所以此處判斷 b必須小于等于a

SafeMath源碼減法

3.乘法,僅限內部調用,返回 uint256

uint256 c = a * b; 容易溢出,比如 a=2,b=2^255 乘積 2^256 剛好溢出。結果取后面的256位(全為0),導致 c=0。

SafeMath源碼乘法

所以使用 (a == 0 || c / a == b),驗證結果的一致性。

4.除法,僅限內部調用,返回 uint256

require(b > 0), 確保被除數不能為0

require(a == b * c + a % b);防止溢出,驗證結果的一致性

SafeMath源碼除法

總結:

不要直接使用簡單的 "+-*/" ,盡量使用 library SafeMath 中的函數,避免整數溢出的隱患。

附:完整源碼
pragma solidity ^0.4.24;

library SafeMath {

/**

* @dev Returns the addition of two unsigned integers, reverting on

* overflow.

*

* Counterpart to Solidity's `+` operator.

*

* Requirements:

* - Addition cannot overflow.

*/

function safeAdd(uint256 a, uint256 b) internal pure returns (uint256) {

uint256 c = a + b;

require(c >= a, "SafeMath: addition overflow");

return c;

}

/**

* @dev Returns the subtraction of two unsigned integers, reverting on

* overflow (when the result is negative).

*

* Counterpart to Solidity's `-` operator.

*

* Requirements:

* - Subtraction cannot overflow.

*/

function safeSub(uint256 a, uint256 b) internal pure returns (uint256) {

return safeSub(a, b, "SafeMath: subtraction overflow");

}

/**

* @dev Returns the subtraction of two unsigned integers, reverting with custom message on

* overflow (when the result is negative).

*

* Counterpart to Solidity's `-` operator.

*

* Requirements:

* - Subtraction cannot overflow.

*

* NOTE: This is a feature of the next version of OpenZeppelin Contracts.

* @dev Get it via `npm install @openzeppelin/[email protected]`.

*/

function safeSub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

require(b <= a, errorMessage);

uint256 c = a - b;

return c;

}

/**

* @dev Returns the multiplication of two unsigned integers, reverting on

* overflow.

*

* Counterpart to Solidity's `*` operator.

*

* Requirements:

* - Multiplication cannot overflow.

*/

function safeMul(uint256 a, uint256 b) internal pure returns (uint256) {

// Gas optimization: this is cheaper than requiring 'a' not being zero, but the

// benefit is lost if 'b' is also tested.

if (a == 0) {

return 0;

}

uint256 c = a * b;

require(c / a == b, "SafeMath: multiplication overflow");

return c;

}

/**

* @dev Returns the integer division of two unsigned integers. Reverts on

* division by zero. The result is rounded towards zero.

*

* Counterpart to Solidity's `/` operator. Note: this function uses a

* `revert` opcode (which leaves remaining gas untouched) while Solidity

* uses an invalid opcode to revert (consuming all remaining gas).

*

* Requirements:

* - The divisor cannot be zero.

*/

function safeDiv(uint256 a, uint256 b) internal pure returns (uint256) {

return safeDiv(a, b, "SafeMath: division by zero");

}

/**

* @dev Returns the integer division of two unsigned integers. Reverts with custom message on

* division by zero. The result is rounded towards zero.

*

* Counterpart to Solidity's `/` operator. Note: this function uses a

* `revert` opcode (which leaves remaining gas untouched) while Solidity

* uses an invalid opcode to revert (consuming all remaining gas).

*

* Requirements:

* - The divisor cannot be zero.

* NOTE: This is a feature of the next version of OpenZeppelin Contracts.

* @dev Get it via `npm install @openzeppelin/[email protected]`.

*/

function safeDiv(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

// Solidity only automatically asserts when dividing by 0

require(b > 0, errorMessage);

uint256 c = a / b;

return c;

}

/**

* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),

* Reverts when dividing by zero.

*

* Counterpart to Solidity's `%` operator. This function uses a `revert`

* opcode (which leaves remaining gas untouched) while Solidity uses an

* invalid opcode to revert (consuming all remaining gas).

*

* Requirements:

* - The divisor cannot be zero.

*/

function safeMod(uint256 a, uint256 b) internal pure returns (uint256) {

return safeMod(a, b, "SafeMath: modulo by zero");

}

/**

* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),

* Reverts with custom message when dividing by zero.

*

* Counterpart to Solidity's `%` operator. This function uses a `revert`

* opcode (which leaves remaining gas untouched) while Solidity uses an

* invalid opcode to revert (consuming all remaining gas).

*

* Requirements:

* - The divisor cannot be zero.

*

* NOTE: This is a feature of the next version of OpenZeppelin Contracts.

* @dev Get it via `npm install @openzeppelin/[email protected]`.

*/

function safeMod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {

require(b != 0, errorMessage);

return a % b;

}

}

 

分享到:更多 ()
區塊鏈神吐槽

來評論吐槽 搶沙發

評論前必須登錄!

 

區塊鏈資源分享

韭菜的自我進化
聚财弥勒 kk棋牌金花作弊器 品牌卫浴代理赚钱吗 福建36选7开奖今晚116期 实体店彩票复式可不可以全包 楚留香采集赚钱吗 梦幻西游动画片 土耳其崩盘靠什么赚钱 159竞彩足球安全吗 广东11选5选号 东方五分彩走势图 体彩p5便民工作室选号推荐 快乐10分中奖规则 北京晒车pk10稳赚技巧 海马玩模拟器怎么赚钱 新快3 上海快3开奖结果爱彩乐