一行代碼蒸發了¥6,447,277,680 人民幣!
現在進入你還是先行者,最后觀望者進場才是韭菜。
美圖董事長蔡文勝曾在三點鐘群,高調的說出了這句話,隨即被大眾瘋傳。
在他發表完言論沒多久,2月美鏈(BEC)上交易所會暴漲4000%,后又暴跌。盡管他多次否認,聰明的網友早已扒出,他與BEC千絲萬縷的關系。
莊家坐莊操控幣價,美圖的股價隨之暴漲,蔡文勝順利完成了他的韭菜收割大計。
但在幣圈,割人者,人恒割之。
隨著BEC智能合約的漏洞的爆出,被黑客利用,瞬間套現拋售大額BEC,6億在瞬間歸零。
而這一切,竟然是因為一個簡單至極的程序Bug。
背景今天有人在群里說,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
那筆操作記錄是 0xad89ff16fd1ebe3a0a7cf4ed282302c06626c1af33221ebe0d3a470aba4a660f
下面我來帶大家看看,黑客是如何實現的!
我們可以看到執行的方法是 batchTransfer
那這個方法是干嘛的呢?(給指定的幾個地址,發送相同數量的代幣)
整體邏輯是你傳幾個地址給我(_receivers),然后再傳給我你要給每個人多少代幣(_value)
然后你要發送的總金額 = 發送的人數* 發送的金額
然后 要求你當前的余額大于 發送的總金額
然后扣掉你發送的總金額
然后 給_receivers 里面的每個人發送 指定的金額(_value)
從邏輯上看,這邊是沒有任何問題的,你想給別人發送代幣,那么你本身的余額一定要大于發送的總金額的!
但是這段代碼卻犯了一個很傻的錯!
代碼解釋這個方法會傳入兩個參數
_receivers
_value
_receivers 的值是個列表,里面有兩個地址
0x0e823ffe018727585eaf5bc769fa80472f76c3d7
0xb4d30cac5124b46c2df0cf3e3e1be05f42119033
_value 的值是 8000000000000000000000000000000000000000000000000000000000000000
我們再查看代碼(如下圖)
我們一行一行的來解釋
uint cnt = _receivers.length;
是獲取 _receivers 里面有幾個地址,我們從上面可以看到 參數里面只有兩個地址,所以 cnt=2,也就是 給兩個地址發送代幣
uint256 amount = uint256(cnt) * _value;
uint256首先uint256(cnt) 是把cnt 轉成了 uint256類型
那么,什么是uint256類型?或者說uint256類型的取值范圍是多少...
uintx 類型的取值范圍是 0 到 2的x次方 -1
也就是 假如是 uint8的話
則 uint8的取值范圍是 0 到 2的8次方 -1
也就是 0 到255
那么uint256 的取值范圍是
0 - 2的256次方-1 也就是 0 到115792089237316195423570985008687907853269984665640564039457584007913129639935
python 算 2的256次方是多少
那么假如說 設置的值超過了 取值范圍怎么辦?這種情況稱為溢出
舉個例子來說明
因為uint256的取值太大了,所以用uint8來 舉例。。。
從上面我們已經知道了 uint8 最小是0,最大是255
那么當我 255 + 1 的時候,結果是啥呢?結果會變成0
那么當我 255 + 2 的時候,結果是啥呢?結果會變成1
那么當我 0 - 1 的時候,結果是啥呢?結果會變成255
那么當我 0 - 2 的時候,結果是啥呢?結果會變成255
那么 我們回到上面的代碼中,
amount = uint256(cnt) * _value
則 amount = 2* _value
但是此時 _value 是16進制的,我們把他轉成 10進制
(python 16進制轉10進制)
可以看到 _value = 57896044618658097711785492504343953926634992332820282019728792003956564819968
那么amount = _value*2 = 115792089237316195423570985008687907853269984665640564039457584007913129639936
可以在查看上面看到 uint256取值范圍最大為 115792089237316195423570985008687907853269984665640564039457584007913129639935
此時,amout已經超過了最大值,溢出 則amount = 0
下一行代碼
require(cnt > 0 && cnt <= 20);
require 語句是表示該語句一定要是正確的,也就是 cnt 必須大于0 且 小于等于20
我們的cnt等于2,通過!
require(_value > 0 && balances[msg.sender] >= amount);
這句要求 _value 大于0,我們的_value是大于0 的
且,當前用戶擁有的代幣余額大于等于 amount,因為amount等于0,所以 就算你一個代幣沒有,也是滿足的!
balances[msg.sender] = balances[msg.sender].sub(amount);
這句是當前用戶的余額 - amount
當前amount 是0,所以當前用戶代幣的余額沒有變動
for (uint i = 0; i < cnt; i++) { balances[_receivers[i]] = balances[_receivers[i]].add(_value); Transfer(msg.sender, _receivers[i], _value); }
這句是遍歷 _receivers中的地址,
對每個地址做以下操作
` balances[_receivers[i]] = balances[_receivers[i]].add(_value);
`
_receivers中的地址 的余額 = 原本余額+value
所以 _receivers 中地址的余額 則加了57896044618658097711785492504343953926634992332820282019728792003956564819968 個代幣!!!
`Transfer(msg.sender, _receivers[i], _value);
}`
這句則只是把贈送代幣的記錄存下來!!!
就一個簡單的溢出漏洞,導致BEC代幣的市值接近歸0
那么,開發者有沒有考慮到溢出問題呢?
其實他考慮了,
可以看如上截圖
除了amount的計算外, 其他的給用戶轉錢 都用了safeMath 的方法(sub,add)
那么 為啥就偏偏這一句沒有用safeMath的方法呢。。。
這就要用寫代碼的人了。。。
啥是safeMathsafeMath 是為了計算安全 而寫的一個library
我們看看他干了啥?為啥能保證計算安全.
function mul(uint256 a, uint256 b) internal constant returns (uint256) { uint256 c = a * b; assert(a == 0 || c / a == b); return c; }
如上面的乘法.
他在計算后,用assert 驗證了下結果是否正確!
如果在上面計算 amount的時候,用了 mul的話,
則 c / a == b
也就是 驗證 amount / cnt == _value
這句會執行報錯的,因為 0 / cnt 不等于 _value
所以程序會報錯!
也就不會發生溢出了...
那么 還有一個小問題,這里的assert 好 require 好像是干的同一件事
都是為了驗證 某條語句是否正確!
那么他倆有啥區別呢?
用了assert的話,則程序的gas limit 會消耗完畢
而require的話,則只是消耗掉當前執行的gas
總結那么 我們如何避免這種問題呢?
我個人看法是
只要涉及到計算,一定要用safeMath
代碼一定要測試!
代碼一定要review!
必要時,要請專門做代碼審計的公司來 測試代碼
這件事后需要如何處理呢?
目前,該方法已經暫停了(還好可以暫停)所以看過文章的朋友 不要去測試了...
不過已經發生了的事情咋辦呢?
我的想法是,快照在漏洞之前,所有用戶的余額情況
然后發行新的token,給之前的用戶 發送等額的代幣...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/24033.html
摘要:金蝶國際針對做空的回應遭遇做空后,金蝶管理層積極應對,第一時間針對指控做出回應,認為金蝶國際的云轉型戰略非常正確,這幾年業績有目共睹,對未來充滿信心。這幾天,金蝶國際可謂喜憂參半!繼3月14日公布其截至2018年12月31日的全年業績,集團收入同比增長21.9%,其中金蝶云業務收入大幅增長49.5%的喜人財報后,3月18日,金蝶國際在Webb-site于其網站上發布的一份突如其來的做空報告襲...
摘要:綠色數據中心的理念,也令順利獲得上海市經濟和信息化委員會的用能指標批準優刻得青浦數據中心獲批上海新建用能指標,這些技術將繼續用于青浦數據中心的建設,發力新基建。該數據中心的設計指標達到。?環保意識的提高,使數據中心的能耗日益成為關注點。近年來,UCloud探索實踐了多項節能減排技術,并在自建的烏蘭察布數據中心取得了良好效果,電能使用效率PUE維持在1.3左右。綠色數據中心的理念,也令UClo...
摘要:優刻得首個自建數據中心選址內蒙古烏蘭察布,全年平均氣溫,氣溫低于的時長超小時。機房余熱回收利用優刻得將這一技術應用于冬季只有左右的烏蘭察布數據中心,每年預計回收廢熱吉焦,一種熱量單位,可實現減少二氧化碳排放量噸,等同于種植了萬棵樹木。碳中和是指國家、企業、產品、活動或個人在一定時間內直接或間接產生的二氧化碳或溫室氣體排放總量,通過植樹造林、節能減排等形式,以抵消自身產生的二氧化碳或溫室氣體排...
閱讀 1684·2021-09-26 09:55
閱讀 3713·2021-09-22 15:31
閱讀 7328·2021-09-22 15:12
閱讀 2209·2021-09-22 10:02
閱讀 4625·2021-09-04 16:40
閱讀 1031·2019-08-30 15:55
閱讀 3018·2019-08-30 12:56
閱讀 1813·2019-08-30 12:44