智能合約是很容易受到攻擊的——合約上存在的bug、用戶的錢包的漏洞、或者設(shè)置上的疏忽,都會(huì)導(dǎo)致被攻擊。如果您使用了智能合約,則必須準(zhǔn)備好應(yīng)急預(yù)案,在大多數(shù)情況下,唯一有效的解決方案是部署新的智能合約實(shí)例,并且將所有數(shù)據(jù)遷移到該實(shí)例中。
如果你計(jì)劃開發(fā)可升級(jí)的智能合約,遷移過程將的最大風(fēng)險(xiǎn)是在升級(jí)機(jī)制的過程中。
1. 你需要智能合約遷移
即使是沒有任何漏洞的智能合約,用戶也可能會(huì)因?yàn)樗借€的丟失而被盜。在這類攻擊中,即使智能合約具備了可升級(jí)的機(jī)制,也可能無法修復(fù)已部署的智能合約,因此需要部署并正確初始化合約的新實(shí)例,以便為用戶恢復(fù)功能,所有開發(fā)人員必須在智能合約設(shè)計(jì)階段就集成遷移功能,并且必須準(zhǔn)備好折中方案進(jìn)行遷移。
遷移有兩個(gè)步驟:
1)恢復(fù)要遷移的數(shù)據(jù)
2)將數(shù)據(jù)寫入新合約
讓我們來看看細(xì)節(jié)、成本和運(yùn)營后果。
2.如何執(zhí)行遷移
第1步:數(shù)據(jù)恢復(fù)
需要從區(qū)塊鏈中的特定區(qū)塊來讀取數(shù)據(jù),如果是從事件(黑客或故障)中恢復(fù),需要在事件發(fā)生之前,使用阻止或過濾攻擊者的操作。
如果可能,先暫停合同,這對(duì)用戶更加透明,并防止了黑客攻擊不懂遷移的用戶。
數(shù)據(jù)恢復(fù)將取決于您的數(shù)據(jù)結(jié)構(gòu):
對(duì)于簡單類型的公共變量(例如uint或address),通過getter的檢索值是微不足道的。對(duì)于私有變量,您可以依賴事件,也可以計(jì)算變量的內(nèi)存偏移量,然后使用getStorageAt函數(shù)檢索。由于元素的數(shù)量是已知的,因此陣列也很容易恢復(fù)。
映射的情況就有點(diǎn)復(fù)雜了,不存儲(chǔ)映射的鍵,需要恢復(fù)它們才能訪問這些值。為簡化離線跟蹤,我們建議在映射中存儲(chǔ)值時(shí)發(fā)出事件。
對(duì)于ERC20智能合約來說,可以通過跟蹤轉(zhuǎn)移事件的地址找到所有持有者的列表,這個(gè)過程很難。
我們準(zhǔn)備了兩個(gè)方案來幫你:
首先,可以掃描區(qū)塊鏈并自行檢索持有者; 在第二種情況下,可以依賴以太網(wǎng)區(qū)塊鏈公開的Google BigTable存檔。
如果您不熟悉web3 API以從區(qū)塊鏈中提取信息,則可以使用ethereum-etl,它提供了一組腳本來簡化數(shù)據(jù)提取。
如果您沒有同步區(qū)塊鏈,則可以使用Google BigQuery API。圖1顯示了如何通過BigQuery收集給定令牌的所有地址:
圖1:使用Google BigQuery恢復(fù)地址0x41424344處令牌的所有Transfer事件
BigQuery提供對(duì)塊編號(hào)的訪問,因此可以調(diào)整此查詢以將事務(wù)返回到特定塊。
一旦恢復(fù)了所有持有者的地址,就可以離線查詢balanceOf功能以恢復(fù)與每個(gè)持有者相關(guān)的余額。過濾余額為空的帳戶。
現(xiàn)在我們知道如何檢索要遷移的數(shù)據(jù),我們就可以將數(shù)據(jù)寫入新合約。
第2步:數(shù)據(jù)寫入
收集數(shù)據(jù)后,就要?jiǎng)?chuàng)建新的智能合約了。
對(duì)于簡單的變量,可以通過智能合約的構(gòu)造函數(shù)來設(shè)置值。
如果數(shù)據(jù)無法保存在單個(gè)中,則情況會(huì)稍微復(fù)雜和昂貴。每個(gè)交易都包含在一個(gè)區(qū)塊中,該區(qū)塊限制了其交易可以使用的gas總量(所謂的“Gas Limit”)。如果交易的gas成本接近或超過此限制,礦工將不會(huì)再打包。因此,如果要遷移大量數(shù)據(jù),則必須將遷移拆分為多個(gè)任務(wù)。
解決方案是在智能合約中添加初始化狀態(tài),只有所有者才能更改狀態(tài)變量,用戶無法執(zhí)行任何操作。
對(duì)于ERC20令牌,該過程將采取以下步驟:
1)在初始化狀態(tài)下部署契約,
2)遷移余額,
3)將合約的狀態(tài)轉(zhuǎn)移到生產(chǎn)狀態(tài)。
4)初始化狀態(tài)可以使用Pausable功能和指示初始化狀態(tài)的布爾值來實(shí)現(xiàn)。
為了降低成本,可以使用批量傳輸功能實(shí)現(xiàn)余額的遷移,該功能允許您在單個(gè)事務(wù)中設(shè)置多個(gè)帳戶:
在遷移合約時(shí),會(huì)出現(xiàn)兩個(gè)主要問題:
遷移成本和對(duì)交易所有什么影響。
3.遷移成本
數(shù)據(jù)的恢復(fù)是在鏈外完成的,因此是免費(fèi)的。Ethereum-etl可以在本地使用。谷歌的BigQuery API提供足夠的免費(fèi)信用來支付其使用。
但是,發(fā)送到網(wǎng)絡(luò)的每個(gè)事務(wù)和新合同存儲(chǔ)的每個(gè)字節(jié)都有成本。
使用圖2的batchTransfer功能,轉(zhuǎn)移200個(gè)賬戶的成本約為2.4M gas,平均gas價(jià)格(10 Gwei)的5.04美元(ETH以今天的價(jià)格計(jì)算)。粗略地說,遷移一個(gè)數(shù)據(jù)需要0.025美元。
如果我們看看按市值排名的前五大ERC20代幣的持有人數(shù):

4.交易所
部署新合約可能會(huì)對(duì)運(yùn)營產(chǎn)生影響。對(duì)于基于token的合同來說,在遷移期間與交換機(jī)協(xié)作非常重要,以確保將列出新合約,并且將丟棄之前的合約。
幸運(yùn)的是,前面的標(biāo)識(shí)遷移事件,表明交流有可能進(jìn)行合作。
智能合約遷移與可升級(jí)智能合約
可升級(jí)的合約有幾個(gè)缺點(diǎn):
· 需要詳細(xì)的EVM和Solidity的專業(yè)知識(shí),基于委托調(diào)用的代理要求開發(fā)人員掌握EVM和Solidity是必要的。
· 增·加了復(fù)雜性和代碼大小,合約更難審查,更有可能會(huì)有bug和安全問題。
· 增加了要處理的密鑰數(shù)量,合約將需要多個(gè)授權(quán)用戶(所有者,升級(jí)者)。授權(quán)用戶越多,攻擊面越大。
· 每筆交易的gas費(fèi)用增加。合約變得比沒有升級(jí)機(jī)制的同一版本更具競(jìng)爭力。
· 他們鼓勵(lì)在部署后解決問題。如果開發(fā)人員知道無法輕松更新合同,他們往往會(huì)更徹底地測(cè)試和審查合約。
· 它們減少了用戶對(duì)合約的信任。用戶需要信任合約的所有者,這會(huì)阻止真正分散的系統(tǒng)。
· 只有在存在強(qiáng)有力的論據(jù)時(shí),合約才應(yīng)具有可升級(jí)機(jī)制,例如:
· 合約需要經(jīng)常更新。如果要定期修改合約,則定期遷移的成本可能高到足以證明可升級(jí)性機(jī)制的合理性。
· 合約要求固定地址。合約的遷移需要使用新地址,這可能會(huì)破壞與第三方的交互(例如與其他合同的交互)。
· 合約遷移實(shí)現(xiàn)了升級(jí)帶來的好處,但缺點(diǎn)很少。升級(jí)相對(duì)于遷移的主要優(yōu)點(diǎn)是升級(jí)成本更低。然而,這種成本并不能證明所有的缺點(diǎn)。
5.小貼士
在合同部署之前準(zhǔn)備遷移過程、使用事件來促進(jìn)數(shù)據(jù)跟蹤。
如果要購買可升級(jí)版的合約,則還必須準(zhǔn)備遷移程序,因?yàn)槟拿荑€可能會(huì)受到損害,或者您的合約可能會(huì)遭受錯(cuò)誤且不可逆轉(zhuǎn)的操縱。
智能合約帶來了新的發(fā)展模式,它們的不可變性要求用戶重新思考他們構(gòu)建應(yīng)用程序的方式,并要求徹底的設(shè)計(jì)和開發(fā)過程。
電子發(fā)燒友App















評(píng)論