👓
NounsDAOのコントラクト解説
NounsDaoのコントラクトを読み解いてみたので、解説します。
ソースコードはGitHubで公開されています。
相関図
コントラクト間の相関図はこんな感じ。
各コントラクトは NounsDAOProxyでアップグレーダブルになっている。
左側のオークション機能と右側の投票機能から成り立っている。
コントラクト解説
NounsAuctionHouse
Nounsで実施されている一日一回のオークションを司っている
入札(createBid)
- オークション参加者が入札額を指定して入札する
- その時点の最高入札額より2%以上高い金額でないと入札できない
- オークション終了時間の5分以内に入札するとオークション終了時間が5分延長される
落札とミント(settleCurrentAndCreateNewAuction)
- オークション中のNounを落札者にトランスファー(_settleAuction)した後、新しいNounをミントしてオークションを開始(_createAuction)する
- トランスファーはNounsTokenのtransferFrom関数を呼び出す
- ミントもNounsTokenのmint関数を呼び出す
- 10回に1回はNoundersへ自動ミントされる
NounsToken
- Nouns独特のドット絵のフルオンチェーンNFT
- ミント時にNounsSeederで各パーツの番号をランダムに指定し、NounsDescriptorV2で画像を生成している
- ERC721Checkpointableという、投票パワー(Nouns保持数)を管理できるように拡張したERC721を継承している(getPriorVotes関数)
NounsLogicV2
- 投票を司っている
- プロポーザルはpropose関数によって作成される。
- propose関数はNounを2体以上保持していないと実行できない(NounsTokenのgetPriorVotes関数でチェック)
- propose関数実行後、プロポーザルはペンディング状態となり、約6日と6時間後(※)に投票を受け付ける
投票受付後約6日と6時間後(※)で投票は締め切られる
※36,000ブロック後。1ブロックは約15秒で生成される - 賛成数が反対数より大きく、賛成数が全体の**%(反対数を考慮した数。解読中...)の場合、プロポーザルは成功状態になる
- 投票は、castVote関数、またはcastRefundableVote関数によって実施する
- castRefundableVote関数で投票すると、投票にかかったガス代が返還される(
2023年1月現在はcastVoteが有効castVote関数とcastRefundableVote関数は両方使われている。基準不明) - 投票時の投票数は、NounsTokenのgetPriorVotes関数によってNouns保有数が計算される
- 成功状態のプロポーザルは、NounsDAOExcutorにトランザクションをキューイングすることができる(queue関数)
- NounsDAOExcutorにキューイングしたトランザクションは、execute関数で実行できる
またはcancel関数でキャンセルもできる - Noundersのみ、veto関数でトランザクションを強制キャンセルすることができる
NounsDAOExcutor
- プロポーザルで取得したい報酬とトランザクション実行内容をキューイングする
- トランザクションは、直接callされるため、NounsLogicV2のプロポーザルには実行する関数(callData)を登録しておく
// solium-disable-next-line security/no-call-value
(bool success, bytes memory returnData) = target.call{ value: value }(callData);
Discussion