1.驗證軟件功能介紹:
Beosin-VaaS的業務邏輯驗證軟件, 是一款用來檢測智能合約上層業務邏輯漏洞的軟件。
基於合約的白皮書, 軟件利用形式化方法, 首先對單個函數進行屬性的描述, 在對單個函數進行屬性的驗證並通過後, 基於這些已驗證屬性, 抽取出高層的狀態屬性, 進而對上層屬性進行自動推理和驗證, 若屬性不滿足, 則會返回一條反例路徑。
2.案例介紹(界面:合約。)
我們可以以下面這個案例來舉例說明。
這裏我們考慮進行一次衆籌,目標是在部署後deadline時間內,收集fundingGoal個以太幣。 如果在該期間收集到相應數額個以太幣,則表明衆籌成功,在這種情況下,受益人可以提取資金。 否則,將認爲衆籌失敗,並允許用戶要求退款。 衆籌合約本身繼承了token合約,並直接收集衆籌期間投入的所有資金。
3.具體合約和函數說明
我們可以進一步得知, 該項目包含了一個Crowdsale合約,繼承一個token合約。
在衆籌合約中, 構造函數會初始化設置衆籌的截止時間deadline, 並添加衆籌目標額度fundingGoal,並在合約中硬編碼受益人的地址beneficiary;
然後會提供回調函數, 提供給用戶來參與投資, 在開放衆籌期間, 只要未達到目標額度, 就允許所有用戶進行投資;
提供一個checkGoalReached()函數, 如果達到衆籌目標, 或者達到了截止時間, 就可以修改狀態標識, 關閉衆籌;
然後會提供響應的transfer()和issue()函數接口, 用於在衆籌分配代幣,以及能夠進行代幣的交易
提供一個safeWithdrawal()函數, 如果衆籌成功, 受益人能夠取出投資人的錢;
最後還提供一個safeClaimRefund()退款接口, 如果衆籌失敗,用戶可以通過該接口完成撤資;
4.結果分析和說明(界面:合約,中間切換到編寫的屬性)
我們這裏已經完成了單個函數的屬性驗證, 可以確認單個函數的功能是符合其屬性規範的, 在此基礎上, 編寫上層屬性進行驗證. 以下, 我們編寫的上層屬性有兩條, 一條是p1, 含義是總是能夠滿足, 一旦調用了safeWithdrawal()或者safeClaimRefund(), 另一個函數就不能夠被成功調用.
P1:
另一條是p2, 表示無論任何情況, 只要成功調用了函數safeWithdrawal(), 衆籌到的總和amountRaised就不會小於目標值.
P2:
好, 我們這裏進行上層屬性的驗證.
(進行驗證操作)
得到輸出結果, 可以看到屬性2是滿足的, 而屬性1並不滿足, 我們查看一下反例的可視化路徑, 可以看到, 確實存在一條路徑, safeWithdrawal()函數和safeClaimRefund()函數可以先後被執行成功.
回到合約中, 根據所提供的反例路徑, 可以看到, 發生該情況是調用回調函數一段時間後, 當前時間超過了衆籌的截止時間, 衆籌的資金總量沒有達到目標fundingGoal, 在checkGoalReached()關閉衆籌之後。此時的合約狀態, 用戶是可以調用 safeClaimRefund選擇退款的. 但是我們可以從結果中發現, 此時依舊可以調用成功回調函數投資, 那麼就出現了後面的狀態可能, 在衆籌失敗之後, 依舊有用戶有意或者無意參與了投資, 導致投資的總額超過了目標, 此時, 能夠再次調用checkGoalReached()函數結束衆籌, 改變狀態標識, 最終受益人能夠在按原始需求, 衆籌失敗的情況下, 且有用戶選擇退款之後, 依舊調用checkGoalReached()取出了所有的投資資金。
最終回到合約, 我們發現, 其實是由於用於投資的回調函數缺少了檢查當前事件是否超過了截止日期, 進而導致的合約漏洞。
可以看到, 在該例子中, 所有的函數其實是滿足其自身的屬性並實現了相應的功能的, 但是由於在合約之間, 函數之間的調用和關聯關係, 才導致出現了這樣一個漏洞。 而該屬性驗證工具的作用也在於此, 它能夠更加高效地發現邏輯屬性漏洞。