security - blockchain - solidity 漏洞2: overflow, underflow (上溢,下溢)
访问量: 1245
refer to:
https://medium.com/hackernoon/hackpedia-16-solidity-hacks-vulnerabilities-their-fixes-and-real-world-examples-f3210eba5148 见第二个例子
上溢:
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 0x000000000000000000000000000000000001 ---------------------------------------- = 0x000000000000000000000000000000000000
下溢
0x000000000000000000000000000000000000 - 0x000000000000000000000000000000000001 ---------------------------------------- = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
一个例子
pragma solidity 0.4.18;
// Contract to test unsigned integer underflows and overflows
// note: uint in solidity is an alias for uint256
// Guidelines: Press "Create" to the right, then check the values of max and zero by clicking "Call"
// Then, call overflow and underflow and check the values of max and zero again
contract OverflowUnderFlow {
uint public zero = 0;
uint public max = 2**256-1;
// zero will end up at 2**256-1
function underflow() public {
zero -= 1;
}
// max will end up at 0
function overflow() public {
max += 1;
}
}
一般说来 下溢 攻击更容易发生,因为网络上的转账 都是 “消耗” gas或者 balance的。
解决方案:使用SafeMath
openzepplin的源代码:
pragma solidity ^0.4.18;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
assert(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
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) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
contract OverflowUnderFlowSafe {
using SafeMath for uint;
uint public zero = 0;
uint public max = 2**256-1;
// Will throw
function underflow() public {
zero = zero.sub(1);
}
// Will throw
function overflow() public {
max = max.add(1);
}
// Contract to test unsigned integer underflows and overflows
// note: uint in solidity is an alias for uint256
// Guidelines: Press "Create" to the right, then check the values of max and zero by clicking "Call"
// Then, call overflow and underflow and check the values of max and zero again
}