區塊鏈研究實驗室|減少智能合約代碼複雜性並提高可維護性

原文鏈接:https://mp.weixin.qq.com/s/2VW7y9xB7pTXhSkJFzDQ0w

在本文中,我將分享一些示例,說明消除特殊情況如何減少代碼複雜性並提高可維護性。

特殊最大值

常見的特殊情況是使用0表示“無最大值”。這種特殊情況通常很容易消除。

Special Expirations

看下面的代碼👇

在這段代碼中,0是一種特殊情況,表示“沒有過期”。這種特殊情況是不直觀的,它增加了require語句的複雜性。

然而,真正的危險是團隊中的一個新開發人員忽略了這個微妙之處,無法處理expiration==0的特殊情況。這很容易導致資金損失或其他嚴重問題。

這樣代碼就更簡單更明顯了:


這裏,我使用的是uint256允許的最大值的expiration,而不是0,當涉及到時間戳時,expiration實際上是無限的。

特殊最大以太幣數量

這是一個非常相似的示例,但這次涉及以太幣:

同樣,我們有一個非直觀的特例,我們可以通過使用一個有效的無限值來解決這個問題: 

2256-1是最大值

注意,同樣的技巧可以概括爲令牌數量或任何值。由於Solidity不能表示大於2256-1的值,因此它始終可以與uint256進行比較,成爲“有效無限”值

解決gas成本問題

通常,在gas成本方面需要進行權衡。人們最終將默認值設爲0的一個典型原因是存儲非零值會耗費大量gas。

如果存儲成本對於您的用例而言是很高的,請考慮以下技巧:

在此代碼中,寫入存儲的_expiration值默認情況下爲0,與以前的特殊含義相同。但是,我介紹了一個輔助函數expiration(),它將0轉換爲不太特殊的值2256-1。這意味着我的其餘代碼無需處理這種特殊情況。

考慮將此技術與自定義的linter規則配對使用,以確保您不會在expiration()函數之外的任何地方直接讀取_expiration。

特殊地址

關於地址,我經常看到兩種特殊情況:

  1. 地址0通常是不允許的。

  2. 不允許使用特定地址(通常是特權角色)。

特別地址0

這是一些熟悉的代碼,其中使用0作爲特殊情況:

 禁止使用地址0通常是爲了保護用戶不受錯誤的影響。將令牌發送到地址0通常不會比將它們發送到地址1更糟糕,但0是默認值,因此更可能由於有錯誤的工具或庫而意外傳入。

我個人不喜歡這種地址0的支票,但這很少有問題。與前面的示例不同,如果開發人員在維護代碼時忘記了這種特殊情況,那麼一切都不會中斷。

特殊角色地址

這段代碼比上一段要麻煩得多:

當我看到這樣的代碼時,我的直接問題是爲什麼所有者地址無法接收令牌。這樣的檢查通常是爲了將安全控制措施放在適當的位置,但通常無法解決Sybil攻擊,因爲系統中的多個地址由同一個人控制。

在這個特定的例子中,所有者可以簡單地接收具有不同地址的令牌。如果這違反了合同的安全性假設,那就有問題了。

像這樣的特殊情況是一種代碼氣息,但這並不意味着它們總是應該被消除。要做的重要事情是記錄爲什麼需要這種特殊情況,並考慮替代方案。

總結

  1. 特殊情況會導致代碼複雜性,從而導致錯誤。

  2. 在可能的情況下,完全消除特殊情況。

  3. 2256-1是最大值的良好替代品。

  4. 地址0的特殊情況通常可以。

  5. 其他特定地址的特殊情況是代碼氣味。

  6. 如果決定在代碼中使用具有特殊意義的值,請嘗試隔離用於處理這些值的代碼。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章