http://www.7klian.com

一行代码蒸发了¥6,447,277,680 人民币

  assert(a == 0 || c / a == b);

  首先 uint256(cnt) 是把cnt 转成了 uint256范例

  其实他思量了,

  也就不会产生溢出了...

  当前amount 是0,所以当前用户代币的余额没有变换

  我能想到的是,快照在裂痕之前,所有用户的余额环境

  uint cnt = _receivers.length;

  

  safeMath 是为了计较安详 而写的一个library

  我们一行一行的来表明

  而require的话,则只是耗损掉当前执行的gas

  代码必然要测试!

  

  uintx 范例的取值范畴是 0 到 2的x次方 -1

  uint256


  那么,开拓者有没有思量到溢出问题呢?

  假如在上面计较 amount的时候,用了 mul的话, 则 c / a == b 也就是 验证 amount / cnt == _value

  57896044618658097711785492504343953926634992332820282019728792003956564819968 个代币!!!

  return c;


  总结

  用了assert的话,则措施的gas limit 会耗损完毕


  http://www.bibaodao.com/blockchain/

  }

  所以 _receivers 中地点的余额,则加了

  除了amount的计较外, 其他的给用户转钱 都用了safeMath 的要领(sub,add)

  

  那么当我 0 - 1 的时候,功效是啥呢?功效会酿成255

  balances[_receivers[i]] = balances[_receivers[i]].add(_value);

  _value 的值是 8000000000000000000000000000000000000000000000000000000000000000

  然后扣掉你发送的总金额

  这句会执行报错的,因为 0 / cnt 不便是 _value

  啥是safeMath

  总结

  这句是当前用户的余额 - amount

  然后你要发送的总金额 = 发送的人数* 发送的金额

  代码必然要review!

  0x0e823ffe018727585eaf5bc769fa80472f76c3d7

  那么 我们如何制止这种问题呢?

  我们可以看到执行的要领是 batchTransfer

  那么 尚有一个小问题,这里的 assert 好 require 仿佛是干的同一件事

  0xad89ff16fd1ebe3a0a7cf4ed282302c06626c1af33221ebe0d3a470aba4a660f

  那么 我们回到上面的代码中,

  这句是遍历 _receivers中的地点, 对每个地点做以下操纵

  我小我私家观点是

  那这个要领是干嘛的呢?(给指定的几个地点,发送沟通数量的代币)

  然后 要求你当前的余额大于 发送的总金额

  从上面我们已经知道了 uint8 最小是0,最大是255

  function mul(uint256 a, uint256 b) internal constant returns (uint256) {

  我们再查察代码(如下图)

  然后刊行新的token,给之前的用户 发送等额的代币...

  是获取 _receivers 内里有几个地点,我们从上面可以看到 参数内里只有两个地点,所以 cnt=2,也就是 给两个地点发送代币

  我们看看他干了啥?为啥能担保计较安详.

  Transfer(msg.sender, _receivers[i], _value); } 这句则只是把赠送代币的记录存下来!!!


  uint256 amount = uint256(cnt) * _value;

  因为uint256的取值太大了,所以用uint8来 举例。。。

  那么他俩有啥区别呢?

  如上面的乘法. 他在计较后,用assert 验证了下功效是否正确!

  可以看到 _value = 57896044618658097711785492504343953926634992332820282019728792003956564819968

  整体逻辑是

  可以在查察上面看到 uint256取值范畴最大为 115792089237316195423570985008687907853269984665640564039457584007913129639935

  _receivers

  我们的cnt便是2,通过!


  那么 amount = _value*2 = 115792089237316195423570985008687907853269984665640564039457584007913129639936

  _value

  balances[msg.sender] = balances[msg.sender].sub(amount);

  }

  0 到115792089237316195423570985008687907853269984665640564039457584007913129639935

  下面我来带各人看看,黑客是如何实现的!

  也就是 0 到255

  amount = uint256(cnt) * _value

  那笔操纵记录是

  0 - 2的256次方-1 也就是

  可是此时 _value 是16进制的,我们把他转成 10进制

  也就是 如果是 uint8的话

  不外已经产生了的工作咋办呢?

  balances[_receivers[i]] = balances[_receivers[i]].add(_value); _receivers中的地点 的余额 = 原本余额+value


  _receivers 的值是个列表,内里有两个地点

  这句要求 value 大于0,我们的value是大于0 的 且,当前用户拥有的代币余额大于便是 amount,因为amount便是0,所以 就算你一个代币没有,,也是满意的!

  那么当我 255 + 2 的时候,功效是啥呢?功效会酿成1

  那么 为啥就偏偏这一句没有用safeMath的要领呢。。。

  

  这件过后需要如那里理惩罚呢?

  Transfer(msg.sender, _receivers[i], _value);

  你传几个地点给我(receivers),然后再传给我你要给每小我私家几多代币(value)


  然后 给receivers 内里的每小我私家发送 指定的金额(value)

  require(_value > 0 && balances[msg.sender] >= amount);

  则 uint8的取值范畴是 0 到 2的8次方 -1

  此时,amout已经高出了最大值,溢出 则 amount = 0

  

  

  for (uint i = 0; i < cnt; i++) {

  都是为了验证 某条语句是否正确!

  下一行代码 require(cnt > 0 && cnt <= 20); require 语句是暗示该语句必然要是正确的,也就是 cnt 必需大于0 且 小于便是20

  那么,什么是uint256范例?可能说uint256范例的取值范畴是几多...

  0xb4d30cac5124b46c2df0cf3e3e1be05f42119033

  所以措施会报错!

  本日有人在群里说,Beauty Chain 美蜜 代码内里有bug,已经有人操作该bug得到了 57,896,044,618,658,100,000,000,000,000,000,000,000,000,000,000,000,000,000,000.792003956564819968 个 BEC

  (python 16进制转10进制)

  这就要用写代码的人了。。。

  须要时,要请专门做代码审计的公司来 测试代码

  可是这段代码却犯了一个很傻的错!


  只要涉及到计较,必然要用safeMath

  就一个简朴的溢出裂痕,导致BEC代币的市值靠近归0


  从逻辑上看,这边是没有任何问题的,你想给别人发送代币,那么你自己的余额必然要大于发送的总金额的!

  代码表明

  

  

  那么uint256 的取值范畴是

  这个要了解传入两个参数

  uint256 c = a * b;

  举个例子来说明

  则 amount = 2* _value

  那么当我 0 - 2 的时候,功效是啥呢?功效会酿成254

  那么当我 255 + 1 的时候,功效是啥呢?功效会酿成0

  今朝,该要领已经暂停了(还好可以暂停)所以看过文章的伴侣 不要去测试了...

  那么如果说 配置的值高出了 取值范畴怎么办?这种环境称为 溢出

  python 算 2的256次方是几多?

  可以看如上截图

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

说点什么吧
  • 全部评论(0
    还没有评论,快来抢沙发吧!

相关文章阅读