区块链智能合约美链攻击分析以及安全库的使用
Posted little_stupid_child
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了区块链智能合约美链攻击分析以及安全库的使用相关的知识,希望对你有一定的参考价值。
1.美链攻击过程
美链代币BEC为发行在以太坊上的ERC20代币,其具体合约的代码在该链接中合约代码。
向美链发起攻击的交易链接为攻击交易hash。
function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) {
uint cnt = _receivers.length;
uint256 amount = uint256(cnt) * _value;
require(cnt > 0 && cnt <= 20);
require(_value > 0 && balances[msg.sender] >= amount);
balances[msg.sender] = balances[msg.sender].sub(amount);
for (uint i = 0; i < cnt; i++) {
balances[_receivers[i]] = balances[_receivers[i]].add(_value);
Transfer(msg.sender, _receivers[i], _value);
}
return true;
美链攻击的具体流程分为以下四步:
1.首先构造一个_value值,使得_receivers.len() * _value产生向上溢出,结果为一个极小值amount。比如使用_receivers.len()为2,_value值为2**255,那么在上述代码中计算得到的amount值为0。
2.amount,value通过require验证。
3.在msg.sender中减去amount数量的代币。
4.为每个_receivers账户增加value数量的代币。
其中value为一个极大值,相当于对美链的BEC代币进行了增发,对应的_receivers账户可以获取大量BECtoken。
2.solidity中上溢与下溢
在solidity中变量进行+、-、*运算时会产生溢出,如加法运算和乘法运算会产生向上溢出,减法运算产生向下溢出。如2**255变量乘以2,获得的结果为0。具体溢出情况可参考以下合约代码:
pragma solidity 0.4.20;
contract TestFlow {
uint256 public zero = 0;
uint256 public max = 2**256 - 1;
uint256 public mm = 2**255;
function subUnderFlow() public constant returns (uint) {
uint256 a = zero - 1;
return a;
}
function addOverFlow() public constant returns (uint) {
uint256 a = max + 1;
return a;
}
function mulOverFlow() public constant returns (uint) {
uint256 a = mm * 2;
return a;
}
}
3.定义安全库
在对数字进行运算时,要采用安全函数,保证结果正确且不发生溢出。安全的数学运算库的使用如下所示。
第一步:导入SafeMath库文件
pragma solidity >=0.4.22 <0.6.0;
/**
* @title SafeMath
* @dev Unsigned math operations with safety checks that revert on error
*/
library SafeMath {
/**
* @dev Multiplies two unsigned integers, reverts on overflow.
*/
function mul(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.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Adds two unsigned integers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
* reverts when dividing by zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
第二步,引用
pragma solidity >=0.4.22 <0.6.0;
import "./safemath.sol";
contract jisuan{
uint a=2;
uint b=5;
uint c=8;
//引入safemath库
using SafeMath for uint256;
//加法
function addNum()public view returns(uint d){
d=a.add(b);
}
//减法
function subNum()public view returns(uint d){
d=b.sub(a);
}
//乘法
function mulNum()public view returns(uint d){
d=a.mul(b);
}
//除法
function divNum()public view returns(uint d){
d=c.div(a);
}
}
以上是关于区块链智能合约美链攻击分析以及安全库的使用的主要内容,如果未能解决你的问题,请参考以下文章