👓

NounsDAOのコントラクト解説

2023/01/09に公開

NounsDaoのコントラクトを読み解いてみたので、解説します。
ソースコードはGitHubで公開されています。
https://github.com/nounsDAO/nouns-monorepo/tree/master/packages/nouns-contracts

相関図

コントラクト間の相関図はこんな感じ。
各コントラクトは 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