首页密报 > 文章列表
「入門科普 」初涉 Solidity:安全、Gas 優化以及創建眾籌平臺

由於有很多公開的優秀在線資源,因此,我不會解釋所有的基本概念,而是嘗試解釋一些值得分享的有趣事物(即安全性和gas優化技巧),並在嘗試解決一些練習時回顧一下我的思考過程。

提示

三種轉移方式:send、transfer 和 call

盡管可以使用這 3 種方法來轉移以太坊,但它們具有值得了解的關鍵區別。send()和transfer()曾經被推薦使用,因為它們會將 gas 支出限製在 2300 gwei。利用這個數量的gas,人們可以進行一些次要的 fallback 操作,比如發出事件,甚至更新存儲,但這還不足以重入合約。然而,這從來都不是避免重入攻擊的好方法,因為 gas 成本會隨著協議更新而變化(即伊斯坦布爾分叉增加了SLOD操作碼的 gas 成本)。

因此,建議使用低級功能call(),默認轉發所有可用的gas。然後,你可以使用 Reentrancy Guard 或 Checks-Effects-Interactions 模式 來保護你的函數。

索引事件參數與非索引(常規)

具有索引參數的事件更容易檢索,因為它們在世界狀態(在logsBloom中)中被特別索引。因此,它們比只有常規參數的事件稍微貴一些。

這個解釋可以通過這個簡單的 Foundry 示例來確認:

image.png

索引事件和非索引事件之間的 gas 費比較。

註意:日誌由主題(最多 4 個)和數據組成。其中一個主題為事件簽名保留,因此你最多可以有 3 個索引參數。

在以太坊黃皮書中,可以斷言每個主題花費 375 gwei,數據中的每個字節花費 8gwei。

image.png

以太坊黃皮書中定義的事件 gas 成本

任務:創建一個基本的眾籌平臺

搭建一個符合以下要求的簡單眾籌平臺的主幹:

  • 任何人都可以創建一個活動(Campaign)來為其項目獲取資金。
  • 每個活動至少必須擁有:

名字

所有者

活動類型(初創公司或慈善機構)。

籌資目標

時間限製,不能超過 60 天

  • 上述所有屬性都必須在活動創建時定義,並且無法被更新。
  • 在達到給定活動的時間限製之前,任何人都可以通過發送以太坊來資助它。達到時限後,便無法再接收資金。
  • 活動的所有者只有在達到時限後才能提取所籌集的以太坊。
  • 所有者提取資金後,應將活動標記為完全資助 FullyFunded(如果籌得資金 >= 資金目標)或部分資助 PartiallyFunded(如果籌得資金 < 資金目標)。
  • 所有者必須能夠取消活動。如果發生這種情況,該活動將無法再收到以太坊。
  • 實施所有相關的事件。

解決方案設計

當有一個想法時,你首先需要弄清楚的是解決方案應該具有的架構設計。在我看來,最合理的做法是為每個活動製定一個獨立的合約,這樣所有者就可以直接與之互動並擁有完全的所有權。因此,我決定創建一個工廠合約 CampaignFactory 和一個名為 Campaign 的活動合約。

image.png

工廠合約的運作模式

鑒於上述的架構,我首先創建了 Campaign 合約,確保它符合所有給定的要求。

你可以在此 GitHub gist中查看完整的腳本https://gist.github.com/0xRusowsky/5b583aeff7e387fa00652a9b079c34ad

首先,我們需要定義變量以及可能需要的任何 枚舉 enum 或 結構 structs。

image.png

註意 owner 必須是一個 payable address,因為它將具有提取資金的能力。

一旦我們設置了所有變量,我們就可以創建合約構造函數。在這種情況下,構造函數將使用 require() 函數來確保截止日期小於 60 天。

由於在 solidity 中的時間戳是 unix 格式(從1970 年1 月1 日開始以表計算)中表示的,因此構造函數_deadline中使用的輸入變量將具有相對範圍(require 語句狀態_deadline <= 3600*24*60)。盡管如此,全局變量deadline將具有絕對引用,因此我們可以將它與任何給定的時間戳進行比較。

image.png

由於 owner 是 a payable address,我們必須更改 _owner 類型以使其符合要求。

在對構建的合約進行編碼之後,我創建了相關的事件和一些修改器,這些修改器將有助於我們在活動功能中實現所需的驗證。

image.png

事件和修飾符的實現。

最後,我們需要實現合約功能。在這種情況下,我們只需要 4 個函數:fallback(), receive(), withdrawFunds(), cancelCampaign().

為了 fallback() 和 receive() 能夠從其他合約以及 EOA 中接收以太幣,我們需要使它們payable。最重要的是,我們還將添加liveCampaign修改器以確保在活動結束後不再收到捐款。

另一個值得一提的話題是如何處理提款。正如之前在提示部分中所解釋的,我們在這裏使用低級函數call()。

640

執行競選合約功能。

至此,活動合約完成。現在,我們只需要再創建一個眾籌工廠合約。

在這種情況下,工廠合約將只有一個函數,該函數將在調用時部署活動合約的新實例。最重要的是,我們還將添加一些映射以更好地處理已部署的活動。這些映射將按所有者(使用數組)跟蹤已部署的活動合約,以及每個人已部署的活動數量(以導航數組)。

image.png

執行眾籌工廠合約。

原文鏈接:https://journal0xrusowsky.substack.com/p/first-interactions-with-solidity?utm_source=twitter&sd=pf

生成海报
请长按保存图片,将内容分享给更多好友