13.0 ETH-美鏈 事件
2018年4月發(fā)生的事件,美鏈是發(fā)行在以太坊上的代幣,這些代幣沒有自己的區(qū)塊鏈,而是以智能合約的形式運行在以太坊的EVM平臺上。發(fā)行這個代幣的智能合約,對應(yīng)的是以太坊狀態(tài)樹的一個節(jié)點,這個節(jié)點有它自己的賬戶余額,就相當(dāng)于這個智能合約一共有多少個以太幣,就是發(fā)行這個代幣的智能合約它的資產(chǎn)有多少個以太幣,然后在這個合約里每個賬戶上有多少個代幣,這個是作為存儲樹中的變量,存儲在智能合約的賬戶里。代幣的發(fā)行、轉(zhuǎn)賬、銷毀都是通過調(diào)用智能合約中的函數(shù)來實現(xiàn)的,這個也是跟以太坊上的以太幣不太一樣的地方,它不像以太坊一樣需要挖礦來維護一個底層的基礎(chǔ)鏈,像以太坊上每個賬戶有多少個以太幣,這個是直接保存在狀態(tài)樹中的變量,然后以太坊上面兩個賬戶轉(zhuǎn)賬是通過發(fā)布一個交易到區(qū)塊鏈上,這個交易會打包到發(fā)布的區(qū)塊鏈上面,而代幣發(fā)生轉(zhuǎn)賬的話實際上就是智能合約上面兩個賬戶之間發(fā)生轉(zhuǎn)賬,通過調(diào)用智能合約上的函數(shù),就可以完成了。每個代幣都可以制定自己的發(fā)行規(guī)則,比如某個代幣是1個以太坊兌換100個代幣,那么比如說從某個外部賬戶轉(zhuǎn)1個以太幣給這個智能合約,這個智能合約就可以給你在這個智能合約里的代幣賬戶上發(fā)送100個代幣,每個代幣賬戶上有多少個代幣的信息都是維護在存儲樹里面,發(fā)行這個代幣的智能合約的存儲樹里面。
以太坊平臺的出現(xiàn)讓發(fā)行代幣提供了方便,包括以前說的eos,這個在上線之前也是作為以太坊上的代幣形式,上線的意思是有自己的基礎(chǔ)鏈了,不用依附在以太坊上了。以太坊發(fā)行代幣的標(biāo)準為ERC20(Ethereum Request for Comments)。
這個是batchTransfer的函數(shù):
這個函數(shù)有兩個參數(shù),第一個參數(shù)是一個數(shù)組,接收者地址的數(shù)組,第二個參數(shù)value是轉(zhuǎn)賬的金額,給每個人轉(zhuǎn)多少。
uint256 amount = uint256(cnt) * _value; //計算一共要轉(zhuǎn)的總金額
require(cnt > 0 && cnt <= 20); //檢查接收者的數(shù)目不超過20個。
require(_value > 0 && balances[msg.sender] >= amount); //檢查發(fā)起調(diào)用函數(shù)的這個賬戶是否有這么多錢。
balances[msg.sender] = balances[msg.sender].sub(amount); //把發(fā)起調(diào)用的賬戶余額減去amount。
下面用一個循環(huán)給每個接收者接收value這么多的代幣。
那么,問題出在哪?
uint256 amount = uint256(cnt) * _value; 當(dāng)value的值很大的時候可能會發(fā)生溢出,那么amount算出來可能是個很小的一個值,所以從調(diào)用者的代幣中減的時候是很小一部分的代幣,但還是給每個receivers增加那么多value的代幣。最后系統(tǒng)中相當(dāng)于多發(fā)行了許多的代幣。
第0號參數(shù)是_receivers數(shù)組在參數(shù)列表中的位置,這里是16進制的,0040對應(yīng)的是4乘16=64,第一個參數(shù)出現(xiàn)在第64個字節(jié)的位置,一行有64個數(shù)字,1個16進制的數(shù)字需要用4個二進制的數(shù)字來表示,64乘4=256位,也就是說一行有32個字節(jié)。所以是從[2]行開始表示receivers,表示了數(shù)組的長度是2,[3] [4]兩行是接受的地址。[1]行表示value的值。注意,[1]行的參數(shù)是80000...再乘以接收者2個,算出來的溢出正好是0。
紅框中可以看到每個地址都是接收了很大數(shù)量的代幣。
攻擊使代幣的價格造成致命性的打擊,差不多快要歸零了。
代幣上市的交易所在發(fā)生攻擊后暫停提幣的功能,并且回滾了交易。
反思
在進行數(shù)學(xué)運算的時候一定要考慮溢出的可能性。solidity有一個safeMath庫,里面提供的操作運算都會自動檢測有沒有出現(xiàn)溢出。
C語言里,兩個數(shù)相乘會有一定的精度損失,再除以一個數(shù),不一定會得到和另外一個數(shù)一模一樣的數(shù)。但是在solidity里面是不存在的,因為兩個數(shù)都是256位的整數(shù),整數(shù)先進行乘法,再進行除法。
batchTransfer的加法和減法都用的safeMath庫,只有乘法不小心沒有使用,結(jié)果釀成了悲劇。曾經(jīng)有人懷疑是不是故意的,但從事件的結(jié)果來看又不像使故意的。
文章來源:http://www.zghlxwxcb.cn/news/detail-426883.html
mul()函數(shù)中,先用a*b = c,再用c/a看看是否等于b,如果發(fā)生溢出的話,assert()會拋出異常。文章來源地址http://www.zghlxwxcb.cn/news/detail-426883.html
到了這里,關(guān)于北京大學(xué)肖臻老師《區(qū)塊鏈技術(shù)與應(yīng)用》ETH筆記 - 13.0 ETH-美鏈 事件的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!