KryptoCamp — Day25 — DAO 合約程式碼研究
今天來仔細研究關於 openzeppelin 文件當中寫到的治理合約應該如何實作,以下附上今天的文件。
在 openzeppelin 提供 Governor 之前,有兩個很用於治理投票的合約分別是 Governor Bravo 與 Governor Alpha,這兩個合約都是用於解決 DAO 與 defi 的治理相關問題,基本上可以認為 Governor Bravo 是 Governor Alpha 的升級版,團隊接下來也只打算維護 Governor Bravo 的合約,Alpha 的合約至今日已經兩年多沒有更新了,以下簡單附上兩者的區別:
而 openzeppelin 跟 Governor Bravo 比起來比較方便的地方是可以很簡單的引入,即使有與 Governor Bravo 不一樣的需求,也可以利用模塊化的部分依序引入自己需要的部分即可,而不用 fork 回來做修改,不過做的事情基本上是差不多的。
另外即使是已經有使用 Governor Bravo 的項目,在 openzeppelin 也提供了相同的接口,就算要切換使用也不會有太大的問題。
為了與 Governor Bravo 兼容,很多 module 都有兩個版本,如果沒有從 Governor Bravo 更換的需求,則通常採用名稱比較短的那個即可。
如果想要在 token 合約上開啟治理功能,那麽 ERC-20 需要引入 ERC20Votes
,如果是 ERC-721 的話則需要引入 ERC721Votes
。
如果你的合約只引入了核心的 Governor,那麼至少還有四件事情是你需要定義的:
- 如何確定投票權
- 要開啟一個投票需要多少票
- 人們在投票時有哪些選擇以及這些選票如何計數
- 應該使用什麼類型的令牌進行投票
你可以選擇自己定義或是直接使用 openzeppelin 提供的 module 。
如果要開啟一個投票的提案,就需要執行 propose
function ,這裡面要帶入四個參數,看 _execute 的程式碼可以知道每個參數都是一組一組的,也就是說每個 targets
會分別對到每一個 values
與 calldatas
,並且依序執行。利用這種方式可以先將我們預期要投票的提案先打包成 calldatas
並投票,提案成的話就可以執行已經打包好的交易。
真正執行投票的時候則是呼叫 castVote
function 來進行。等到投票都進行完成,則依據是否有使用時間鎖,若是有則要先呼叫 queue
function 進入列隊,並且等到等待足夠的時間後就可以執行 execute
執行投票的提案。
或是沒有使用時間鎖的話,則可以在投票結果出來後直接執行 execute
function ,執行時的邏輯可以看這裡。在其中看到的 call
function 是一個低階的 function 呼叫方法,一般而言不太推薦用這個呼叫方式,但是當你是調用 fallback function 時這是比較推薦使用方式。
關於 fallback function 可以參考這個影片。