👓

[Bunzz Decipher] Nounsの『NounsToken』コントラクトを理解しよう!

2023/08/29に公開

はじめに

初めまして。
CryptoGamesというブロックチェーンゲーム企業でエンジニアをしている cardene(かるでね) です!
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。

https://cryptogames.co.jp/

代表的なゲームはクリプトスペルズというブロックチェーンゲームです。

https://cryptospells.jp/

今回はBunzzの新機能『DeCipher』を使用して、Nounsの「NounsToken」コントラクトを見てみようと思います。

DeCipher』はAIを使用してコントラクトのドキュメントを自動生成してくれるサービスです。

https://www.bunzz.dev/decipher

詳しい使い方に関しては以下の記事を参考にしてください!

https://zenn.dev/heku/articles/33266f0c19d523

今回使用する『DeCipher』のリンクは以下になります。

https://app.bunzz.dev/decipher/chains/1/addresses/0x9C8fF314C9Bc7F6e59A9d9225Fb22946427eDC03

Etherscanのリンクは以下になります。

https://etherscan.io/address/0x9C8fF314C9Bc7F6e59A9d9225Fb22946427eDC03

概要

NounsTokenコントラクトは、Nouns DAOプロジェクトの中心的なコントラクトです。
Nouns DAOは、非代替可能トークン(NFT)と呼ばれるユニークなデジタルアセットを作成し管理する分散型自治組織(DAO)です。

NounsTokenコントラクトの目的

NounsTokenコントラクトは、Ethereumブロックチェーン上に存在するプログラムです。
このコントラクトは、「Noun」と呼ばれる特別なNFTの作成、所有権の管理、そして転送を担当しています。
Nounはそれぞれ異なり、コントラクト内で一意の番号(トークンID)で区別されます。
また、NounsTokenコントラクトは、Nounを不要になった時に破棄(燃焼)する機能も持っています。

このコントラクトは、ERC721という規格に従って作られています。
ERC721は、Ethereumブロックチェーン上でNFTを作成し管理するための共通のルールです。
これにより、NounERC721トークンをサポートする他のコントラクトやプラットフォームとも連携できます。
例えば、NFTを買ったり売ったりできるデジタルマーケットプレイスでも利用されます。

NounsTokenコントラクトの役割

1. Nounのミンティング(作成)

NounsTokenコントラクトは新しいNounを作成する機能を持っています。
これはmintできるアドレスである「minter」によって制御されます。
minterは、新しいNounを作成する唯一のエンティティです。
つまり、新しいNounが作られる際にはminterによって管理されます。

2. 所有権の管理

コントラクトは、各Nounの所有者を追跡して管理します。
Nounが一人から別の人へ移動する際には、コントラクトが所有権の記録を更新します。
これにより、Nounの所有者が変わったときでも正確な情報が保持されます。

3. Nounの燃焼(破棄)

コントラクトは、Nounを破壊して存在を消すこともできます。
この操作を「バーン」と呼びます。
不要なNounを取り除くために使用されることがあります。

4. ミンターのロック

コントラクトには、minterをロックする機能があります。
これにより、新しいNounを作成できる権限を変更することを防ぐことができます。
一度ロックされると、minterの変更が制限されます。

5. ディスクリプタとシーダーの設定

コントラクトには、ディスクリプタとシーダーを設定しロックする機能もあります。
ディスクリプタは、各Nounに関連する詳細情報を生成します。
これにはNounの名前、説明、画像などが含まれます。
シーダーは、各Nounに対してユニークなシード(種)を生成し、それを用いてNounの独自の外観や特性を作成します。

これらの要素を通じて、NounsTokenコントラクトはNounの作成から管理、転送、破壊までのさまざまな重要な機能を提供しています。

Web3、ブロックチェーン、dAppの観点からNounsTokenコントラクトを理解する

Web3の観点

Web3は、ブロックチェーン技術を活用して分散型アプリケーション(dApp)を構築するための技術です。
NounsTokenコントラクトは、dAppのバックエンドロジックやデータストレージを提供します。
ユーザーはWeb3を介してNounsTokenコントラクトとやり取りし、Nounの作成や所有権の管理などの操作を行うことができます。
これによって、分散化された透明性のあるアプリケーションが実現されます。

ブロックチェーンの観点

NounsTokenコントラクトは、Ethereumブロックチェーン上で不変のスマートコントラクトとして存在します。
ブロックチェーンは分散化された台帳であり、NounsTokenコントラクトによるすべてのアクションはブロックチェーン上に永久に記録されます。
これにより、Nounの作成、転送、バーンなどの過程が透明かつ改ざん不可能になります。

dAppの観点

dAppは、ユーザーが直接操作する分散型アプリケーションです。
NounsTokenコントラクトは、このdAppのエンジンとなる部分です。
ユーザーはdAppを通じてNounsTokenコントラクトの機能を利用し、Nounの作成や所有権の管理、転送、バーンなどを行うことができます。
Nouns DAOプロジェクトの中心的な機能を提供する役割を果たしています。

関連リンク

使い方

開発者の視点からNounsTokenコントラクトを使用する手順をステップバイステップで説明していきます。
NounsTokenコントラクトは、トークンの発行、転送、バーンなどを管理し、minterdescriptorseederを設定・ロックします。

NounsTokenコントラクトの使用手順

  1. コントラクトのセットアップ
    NounsTokenコントラクトをEthereumネットワークに展開します。
    これは、TruffleHardhatなどのツールを使用して行います。

  2. Nounders DAOアドレスの設定
    setNoundersDAO(address noundersDAO)関数を呼び出し、Nounders DAOのアドレスを指定します。
    これにより、Nounをミンティングできる権限を持つ組織が設定されます。

  3. minterの設定
    setMinter(address minter)関数を呼び出し、minterのアドレスを指定します。
    これにより、Nounを発行できる権限を持つアドレスが設定されます。
    minterの変更を防ぎたい場合は、lockMinter()関数を呼び出してminterをロックします。
    これにより、将来の更新が制限されます。

  4. ディスクリプタの設定
    setDescriptor(INounsDescriptor descriptor)関数を呼び出し、ディスクリプタのアドレスを指定します。
    これにより、各NounのトークンURIを生成するディスクリプタが設定されます。
    ディスクリプタの変更を防ぎたい場合は、lockDescriptor()関数を呼び出してディスクリプタをロックします。
    これにより、将来の更新が制限されます。

  5. シーダーの設定
    setSeeder(INounsSeeder seeder)関数を呼び出し、シーダーのアドレスを指定します。
    これにより、各Nounのシードを生成するシーダーが設定されます。
    シーダーの変更を防ぎたい場合は、lockSeeder()関数を呼び出してシーダーをロックします。
    これにより、将来の更新が制限されます。

  6. Nounのミント
    mint()関数を呼び出して新しいNounを発行します。
    この関数は新しく発行されたNounのトークンIDを返します。

  7. Nounのバーン
    burn(uint256 tokenId)関数を呼び出し、バーンさせたいNounのトークンIDを指定します。
    これにより、指定したNounが破棄され、流通から削除されます。

  8. NounのデータURIの取得
    dataURI(uint256 tokenId)関数を呼び出し、指定したNounのトークンIDを指定します。
    これにより、指定したNounのデータURIが返されます。

⚠️ 注意
実際にメインネットにデプロイする前に、必ずテストネットでコントラクトの操作を試して、エラーやバグによる資金の損失を避けるようにしてください。

パラメータ

_noundersDAO

Nounders DAOコントラクトのアドレス。

_minter

ミントできるアドレス。

_descriptor

NounsDescriptorコントラクトのアドレス。

_seeder

NounsSeederコントラクトのアドレス。

_proxyRegistry

ProxyRegistryコントラクトのアドレス。

コントラクト

NounsToken

noundersDAO

noundersDAO
address public noundersDAO;

概要
Nounders DAOのコントラクトアドレス。


minter

minter
address public minter;

概要
Nounsをミント(作成)する権限を持つアドレス。


descriptor

descriptor
INounsDescriptor public descriptor;

概要
NounのトークンURI(メタデータ)を生成するためのディスクリプタのアドレス。


seeder

seeder
INounsSeeder public seeder;

概要
Nounのシードを生成するためのシーダーのアドレス。

詳細
この変数には、Nounの独自の特性や属性を生成するためのシーダーのアドレスが格納されます。


isMinterLocked

isMinterLocked
bool public isMinterLocked;

概要
minterのアドレスがロックされているかどうかを示す。

詳細
この変数はブール値(真偽値)を持ち、trueの場合はminterのアドレスがロックされていることを示します。
ロックされたミンターのアドレスは変更できなくなります。


isDescriptorLocked

isDescriptorLocked
bool public isDescriptorLocked;

概要
ディスクリプタのアドレスがロックされているかどうかを示す。

詳細
この変数はブール値(真偽値)を持ち、trueの場合はディスクリプタのアドレスがロックされていることを示します。
ロックされたディスクリプタのアドレスは変更できなくなります。


isSeederLocked

isSeederLocked
bool public isSeederLocked;

概要
シーダーのアドレスがロックされているかどうかを示す。

詳細
この変数はブール値(真偽値)を持ち、trueの場合はシーダーのアドレスがロックされていることを示します。
ロックされたシーダーのアドレスは変更できなくなります。


seeds

seeds
mapping(uint256 => INounsSeeder.Seed) public seeds;

概要
Nounのシード情報を格納するマッピング変数。

詳細
NounのトークンIDに対するシード情報を保持します。
シード情報には独自の属性や特性が含まれます。


_currentNounId

_currentNounId
uint256 private _currentNounId;

概要
現在のNounのID。

詳細
新しいNounがミントされるたびに、このIDが増加します。


_contractURIHash

_contractURIHash
string private _contractURIHash = 'QmZi1n79FqWt2tTLwCqiy6nLM6xLGRsEPQ5JmReJQKNNzX';

概要
コントラクトレベルのメタデータのIPFSコンテンツハッシュ。

詳細
コントラクト全体に関連するメタデータのIPFSコンテンツハッシュが格納されます。
このハッシュはコントラクトの詳細な情報を識別します。


proxyRegistry

proxyRegistry
IProxyRegistry public immutable proxyRegistry;

概要
OpenSeaのProxy Registryのコントラクトアドレス。

詳細
OpenSeaのProxy Registryのスマートコントラクトのアドレスが格納されます。
OpenSeaのNFTプラットフォームとの連携に使用されます。


whenMinterNotLocked

whenMinterNotLocked
modifier whenMinterNotLocked() {
    require(!isMinterLocked, 'Minter is locked');
    _;
}

概要
minterがロックされていないことを確認するための修飾子。

詳細
minterがロックされていない場合にのみ関数の実行を許可します。
もしミンターがロックされている場合、エラーメッセージが表示されます。


whenDescriptorNotLocked

whenDescriptorNotLocked
modifier whenDescriptorNotLocked() {
    require(!isDescriptorLocked, 'Descriptor is locked');
    _;
}

概要
ディスクリプタがロックされていないことを確認するための修飾子。

詳細
ディスクリプタがロックされていない場合にのみ関数の実行を許可します。
もしディスクリプタがロックされている場合、エラーメッセージが表示されます。


whenSeederNotLocked

whenSeederNotLocked
modifier whenSeederNotLocked() {
    require(!isSeederLocked, 'Seeder is locked');
    _;
}

概要
シーダーがロックされていないことを確認するための修飾子。

詳細
シーダーがロックされていない場合にのみ関数の実行を許可します。
もしシーダーがロックされている場合、エラーメッセージが表示されます。


onlyNoundersDAO

onlyNoundersDAO
modifier onlyNoundersDAO() {
    require(msg.sender == noundersDAO, 'Sender is not the nounders DAO');
    _;
}

概要
送信者がnounders DAOであることを確認するための修飾子。

詳細
送信者がnounders DAOのアドレスと一致する場合にのみ関数の実行を許可します。
一致しない場合、エラーメッセージが表示されます。


onlyMinter

onlyMinter
modifier onlyMinter() {
    require(msg.sender == minter, 'Sender is not the minter');
    _;
}

概要
送信者がminterであることを確認するための修飾子。

詳細
送信者がミンターのアドレスと一致する場合にのみ関数の実行を許可します。
一致しない場合、エラーメッセージが表示されます。


contractURI

contractURI
function contractURI() public view returns (string memory) {
    return string(abi.encodePacked('ipfs://', _contractURIHash));
}

概要
コントラクトのメタデータのIPFS URIを取得する関数。

詳細
この関数は、IPFS URIの形式でコントラクトのメタデータのURIを返します。
メタデータは、コントラクトに関する追加情報を提供します。

戻り値

  • memory
    • コントラクトのメタデータのIPFS URI。

setContractURIHash

setContractURIHash
function setContractURIHash(string memory newContractURIHash) external onlyOwner {
    _contractURIHash = newContractURIHash;
}

概要
_contractURIHashを設定する関数。
コントラクトのオーナーのみが呼び出すことができます。

詳細
新しいコントラクトのメタデータのIPFS URIハッシュを設定します。
メタデータのURIはIPFSのハッシュとして保存されます。

引数

  • newContractURIHash
    • 新しいコントラクトのメタデータのIPFS URIハッシュ。

戻り値
なし


isApprovedForAll

isApprovedForAll
function isApprovedForAll(address owner, address operator) public view override(IERC721, ERC721) returns (bool) {
    if (proxyRegistry.proxies(owner) == operator) {
        return true;
    }
    return super.isApprovedForAll(owner, operator);
}

概要
所有者とオペレーターのアドレスを受け取り、所有者がOpenSeaのプロキシコントラクトのオペレーターか確認する関数。

詳細
所有者とオペレーターのアドレスを受け取り、所有者がOpenSeaのプロキシコントラクトのオペレーターであれば、trueを返します。
それ以外の場合は、親クラスのisApprovedForAll関数を呼び出して結果を返します。

引数

  • owner
    • 所有者のアドレス。
  • operator
    • オペレーターのアドレス。

戻り値

  • bool
    • 承認されているかどうかを示す真偽値。

mint

mint
function mint() public override onlyMinter returns (uint256) {
    if (_currentNounId <= 1820 && _currentNounId % 10 == 0) {
        _mintTo(noundersDAO, _currentNounId++);
    }
    return _mintTo(minter, _currentNounId++);
}

概要
Nounをミントする関数。

詳細
現在のNoun IDが1820以下であり、かつ10で割った余りが0の場合、noundersDAOnoundersNounをミントします。
それ以外の場合は、minterに通常のNounをミントします。
0から始まる10個のNounごとに、183個のnounder Noun(5年間の24時間オークション)がnoundersにミントされます。

戻り値

  • uint256
    • ミントされたNounのID。

burn

burn
function burn(uint256 nounId) public override onlyMinter {
    _burn(nounId);
    emit NounBurned(nounId);
}

概要
Nounを燃やす関数。

詳細
指定されたNoun IDのNounを燃やします。
Nounが燃やされると、それに関する情報は永久に削除されます。

引数

  • nounId
    • 燃やすNounのID。

戻り値
なし


tokenURI

tokenURI
function tokenURI(uint256 tokenId) public view override returns (string memory) {
    require

(_exists(tokenId), 'NounsToken: 存在しないトークンのURIクエリ');
    return descriptor.tokenURI(tokenId, seeds[tokenId]);
}

概要
特定のNFTアセットのための一意のUniform Resource Identifier(URI) を取得する関数。

詳細
トークンIDを受け取り、そのトークンに関連するメタデータのURIを返します。
対応するNounが存在しない場合、エラーメッセージが表示されます。

引数

  • tokenId
    • 取得したいトークンのID。

戻り値

  • string memory
    • メタデータのURI。

dataURI

dataURI
function dataURI(uint256 tokenId) public view override returns (string memory) {
    require(_exists(tokenId), 'NounsToken: 存在しないトークンのURIクエリ');
    return descriptor.dataURI(tokenId, seeds[tokenId]);
}

概要
トークンIDを受け取り、そのトークンに関連するデータURIを返す関数。

詳細
tokenURIに似た関数ですが、常にベース64エンコードされたデータURIを提供し、JSONの内容を直接インラインで含みます。
対応するNounが存在しない場合、エラーメッセージが表示されます。

引数

  • tokenId
    • 取得したいトークンのID。

戻り値

  • string memory
    • データURI。

setNoundersDAO

setNoundersDAO
function setNoundersDAO(address _noundersDAO) external override onlyNoundersDAO {
    noundersDAO = _noundersDAO;

    emit NoundersDAOUpdated(_noundersDAO);
}

概要
nounders DAOのコントラクトアドレスを設定する関数。
ロックされていない場合にのみ、nounders DAOコントラクトがこの関数を呼び出すことができます。

詳細
nounders DAOのアドレスを受け取り、新しいアドレスに更新します。
更新後にNoundersDAOUpdatedイベントが発行されます。

引数

  • _noundersDAO
    • 新しいnounders DAOのアドレス。

戻り値
なし


setMinter

setMinter
function setMinter(address _minter) external override onlyOwner whenMinterNotLocked {
    minter = _minter;

    emit MinterUpdated(_minter);
}

概要
トークンのminterを設定する関数。
ロックされていない場合にのみ、コントラクトのオーナーがこの関数を呼び出すことができます。

詳細
minterのアドレスを受け取り、新しいアドレスに更新します。
更新後にMinterUpdatedイベントが発行されます。

引数

  • _minter
    • 新しいminerのアドレス。

戻り値
なし


lockMinter

lockMinter
function lockMinter() external override onlyOwner whenMinterNotLocked {
    isMinterLocked = true;

    emit MinterLocked();
}

概要
minterをロックする関数。

詳細
実行すると、minterがロックされ、以降の変更ができなくなります。
ロックされていない場合にのみ、コントラクトのオーナーがこの関数を呼び出すことができます。
この操作は元に戻すことができず、慎重に実行する必要があります。
ロックされた後にMinterLockedイベントが発行されます。


setDescriptor

setDescriptor
function setDescriptor(INounsDescriptor _descriptor) external override onlyOwner whenDescriptorNotLocked {
    descriptor = _descriptor;

    emit DescriptorUpdated(_descriptor);
}

概要
トークンのURIディスクリプタを設定する関数。

詳細
ロックされていない場合にのみ、コントラクトのオーナーがこの関数を呼び出すことができます。
設定後にDescriptorUpdatedイベントが発行されます。

引数

  • INounsDescriptor _descriptor
    • 新しいURIディスクリプタのインターフェース。

戻り値
なし


lockDescriptor

lockDescriptor
function lockDescriptor() external override onlyOwner whenDescriptorNotLocked {
    isDescriptorLocked = true;

    emit DescriptorLocked();
}

概要
ディスクリプタをロックする関数。

詳細
実行すると、ディスクリプタがロックされ、以降の変更ができなくなります。
ロックされていない場合にのみ、コントラクトのオーナーがこの関数を呼び出すことができます。
この操作は元に戻すことができず、慎重に実行する必要があります。
ロックされた後にDescriptorLockedイベントが発行されます。

戻り値
なし


setSeeder

setSeeder
function setSeeder(INounsSeeder _seeder) external override onlyOwner whenSeederNotLocked {
    seeder = _seeder;

    emit SeederUpdated(_seeder);
}

概要
トークンのシーダーを設定する関数。

詳細
ロックされていない場合にのみ、コントラクトのオーナーがこの関数を呼び出すことができます。
新しいシーダーのインターフェースを受け取り、それを設定します。
設定後にSeederUpdatedイベントが発行されます。

引数

  • INounsSeeder _seeder
    • 新しいシーダーのインターフェース。

戻り値
なし


lockSeeder

lockSeeder
function lockSeeder() external override onlyOwner whenSeederNotLocked {
    isSeederLocked = true;

    emit SeederLocked();
}

概要
シーダーをロックする関数。

詳細
実行すると、シーダーがロックされ、以降の変更ができなくなります。
ロックされていない場合にのみ、コントラクトのオーナーがこの関数を呼び出すことができます。
この操作は元に戻すことができず、慎重に実行する必要があります。
ロックされた後にSeederLockedイベントが発行されます。

戻り値
なし


_mintTo

_mintTo
function _mintTo(address to, uint256 nounId) internal returns (uint256) {
    INounsSeeder.Seed memory seed = seeds[nounId] = seeder.generateSeed(nounId, descriptor);

    _mint(owner(), to, nounId);
    emit NounCreated(nounId, seed);

    return nounId;
}

概要
指定したアドレスにnounIdNounをミントする関数。

詳細
指定したアドレスNounをミントします
また、それに対応するシードを生成し、NounCreatedイベントを発行します。

引数

  • to
    • Nounをミントするアドレス。
  • nounId
    • ミントするNounのID。

戻り値

  • uint256
    • ミントされたNounのID。

イベント

ERC721Checkpointable

decimals

decimals
uint8 public constant decimals = 0;

概要
ERC20規約に従って小数点以下の桁数を定義。

詳細
トークンの小数点以下の桁数を示します。
ERC20トークンは一般的に小数点以下の桁数を持つことができますが、このトークンでは小数点以下の桁数を0として定義しています。


_delegates

_delegates
mapping(address => address) private _delegates;

概要
各アカウントのデリゲートを記録する配列。

詳細
各アカウントのアドレスをキーとして、そのアカウントのデリゲートのアドレスを値として関連付けます。
デリゲートとは、代理投票権を持つアカウントを指します。


Checkpoint

:::details

struct Checkpoint {
    uint32 fromBlock;
    uint96 votes;
}

:::

概要
特定のブロックからの投票数のチェックポイントを示す構造体。

詳細
投票数の変化を特定のブロックから記録するために使用されます。
fromBlockはチェックポイントが記録されたブロック番号を、votesはそのブロックでの投票数を示します。


checkpoints

checkpoints
mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;

概要
各アカウントの投票チェックポイントをインデックスごとに記録するマッピング配列。

詳細
各アカウントのアドレスをキーとし、インデックスをサブキーとして、投票チェックポイントを関連付けます。
各チェックポイントは特定のブロックからの投票数を示すものです。

パラメータ

  • address
    • アカウントのアドレス。
  • uint32
    • チェックポイントのインデックス。

numCheckpoints

numCheckpoints
mapping(address => uint32) public numCheckpoints;

概要
各アカウントの投票チェックポイントの数を記録するマッピング配列。

詳細
各アカウントのアドレスをキーとして、投票チェックポイントの数を関連付けます。
投票が行われるたびに新しいチェックポイントが作成され、その数が増加します。

パラメータ

  • address
    • アカウントのアドレス。

DOMAIN_TYPEHASH

DOMAIN_TYPEHASH
bytes32 public constant DOMAIN_TYPEHASH =
    keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');

概要
EIP712ドメインのタイプハッシュを示します。

詳細
EIP712は、スマートコントラクトによるメッセージ署名の標準化に関する提案です。
この定数は、EIP712メッセージのドメインを定義する際に使用されるタイプハッシュです。


DELEGATION_TYPEHASH

DELEGATION_TYPEHASH
bytes32 public constant DELEGATION_TYPEHASH =
    keccak256('Delegation(address delegatee,uint256 nonce,uint256 expiry)');

概要
コントラクトで使用されるデリゲーション構造体のEIP712タイプハッシュを示します。

詳細
この定数は、コントラクト内でデリゲーションの署名を作成および検証する際に使用されるEIP712タイプハッシュです。
デリゲーションは、アカウントが投票権を他のアカウントに委任する操作を指します。


nonces

nonces
mapping(address => uint256) public nonces;

概要
アカウントごとの署名やデリゲーションのためのnonce(トランザクション番号)を記録するマッピング配列。

詳細
各アカウントのアドレスをキーとして、nonce(トランザクション番号)を関連付けます。
nonceは署名やデリゲーション操作のセキュリティを確保するために使用されます。

パラメータ

  • address
    • アカウントのアドレス。

votesToDelegate

votesToDelegate
function votesToDelegate(address delegator) public view returns (uint96)

概要
デリゲータがデリゲートできる投票数を取得する関数。
デリゲータの現在の残高となります。

詳細
指定されたデリゲータの現在の残高を取得し、それをuint96の形式に変換して返します。

引数

  • delegator
    • デリゲータのアドレス。

戻り値

  • uint96
    • デリゲータがデリゲートできる投票数。

delegates

delegates
function delegates(address delegator) public view returns (address)

概要
デリゲータのアドレスを取得する関数。
デリゲーションされていない場合、デリゲータの自身のアドレスを返します。

引数

  • `delegator
    • デリゲータのアドレス。

戻り値

  • address
    • デリゲータのアドレス。

_beforeTokenTransfer

_beforeTokenTransfer
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override

概要
トークンの送信に伴ってデリゲートの投票数を更新する関数。

詳細
トークンの送信前に呼び出されます。
トークンの送信に伴って、送信元アドレスと送信先アドレスのデリゲートの投票数を更新します。

引数

  • from
    • トークンの送信元アドレス。
  • to
    • トークンの送信先アドレス。
  • tokenId
    • トークンのID。

戻り値
なし


delegate

delegate
function delegate(address delegatee) public

概要
ユーザーが自身の投票権をデリゲートする関数。

詳細
指定されたデリゲート先のアドレスに自身の投票権をデリゲートします。
デリゲート先のアドレスが0x0の場合、デリゲート先を呼び出し元(msg.sender)に設定します。

引数

  • delegatee
    • デリゲート先のアドレス。

戻り値
なし


delegateBySig

delegateBySig
function delegateBySig(
    address delegatee,
    uint256 nonce,
    uint256 expiry,
    uint8 v,
    bytes32 r,
    bytes32 s
) public

概要
署名を使用して投票権をデリゲートする関数。

詳細
署名を使用して投票権をデリゲートします。
署名が有効であること、nonceが正しいこと、有効期限内であることが確認されます。

引数

  • delegatee
    • デリゲート先のアドレス。
  • nonce
    • ノンス(トランザクション番号)。
  • expiry
    • 署名の有効期限。
  • v
    • 署名の回復バイト。
  • r
    • ECDSA署名のr値。
  • s
    • ECDSA署名のs値。

戻り値
なし


getCurrentVotes

getCurrentVotes
function getCurrentVotes(address account) external view returns (uint96)

概要
指定されたアカウントの現在の投票数を取得する関数。

詳細
指定されたアカウントの最新の投票チェックポイントを取得し、その中の投票数を返します。

引数

  • account
    • 投票数を取得するアカウントのアドレス。

戻り値

  • uint96
    • 指定されたアカウントの現在の投票数。

getPriorVotes

getPriorVotes
function getPriorVotes(address account, uint256 blockNumber) public view returns (uint96)

概要
特定のブロック番号におけるアカウントの過去の投票数を取得する関数。

詳細
指定されたブロック番号におけるアカウントの過去の投票チェックポイントを取得し、その中の投票数を返します。

引数

  • account
    • 投票数を取得するアカウントのアドレス。
  • blockNumber
    • ブロック番号。

戻り値

  • uint96
    • 指定されたアカウントの指定されたブロック番号における過去の投票数。

_delegate

_delegate
function _delegate(address delegator, address delegatee) internal

概要
デリゲータが投票権をデリゲートするた関数。

詳細
デリゲータが指定されたデリゲート先に投票権をデリゲート(委任)します。
その際、現在のデリゲートとデリゲート先の投票数を更新します。

引数

  • delegator
    • デリゲータのアドレス。
  • delegatee
    • デリゲート先のアドレス。

戻り値
なし


_moveDelegates

_moveDelegates
function _moveDelegates(
    address srcRep,
    address dstRep,
    uint96 amount
) internal

概要
デリゲート先の変更に伴って投票数を移動する関数。

詳細
デリゲート先の変更に伴って、投票数の移動を行います。
送信元と送信先が異なる場合かつ移動する投票数が0より大きい場合に実行されます。

引数

  • srcRep
    • 移動元のデリゲート先のアドレス。
  • dstRep
    • 移動先のデリゲート先のアドレス。
  • amount
    • 移動する投票数。

戻り値
なし


_writeCheckpoint

_writeCheckpoint
function _writeCheckpoint(
    address delegatee,
    uint32 nCheckpoints,
    uint96 oldVotes,
    uint96 newVotes
) internal

概要
投票数のチェックポイントを書き込む関数。

詳細
指定されたデリゲート先に対して投票数のチェックポイントを書き込みます。
チェックポイントがすでに存在する場合は更新し、存在しない場合は新たに作成します。

引数

  • delegatee
    • デリゲート先のアドレス。
  • nCheckpoints
    • チェックポイントの数。
  • oldVotes
    • 更新前の投票数。
  • newVotes
    • 更新後の投票数。

戻り値
なし


safe32

safe32
function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32)

概要
uint256型をuint32型に安全に変換する関数。

詳細
指定されたuint256型の値をuint32型に変換します。
変換に失敗する場合、エラーメッセージを表示してリバートします。

引数

  • n
    • 変換する値。
  • errorMessage
    • エラーメッセージ。

戻り値

  • uint32
    • 変換後の値。

safe96

safe96
function safe96(uint256 n, string memory errorMessage) internal pure returns (uint96)

概要
uint256型をuint96型に安全に変換する関数。

詳細
指定されたuint256型の値をuint96型に変換します。
変換に失敗する場合、エラーメッセージを表示してリバートします。

引数

  • n
    • 変換する値。
  • errorMessage
    • エラーメッセージ。

戻り値

  • uint96
    • 変換後の値。

add96

add96
function add96(
    uint96 a,
    uint96 b,
    string memory errorMessage
) internal pure returns (uint96)

概要
uint96型の2つの数値を加算する関数。

詳細
指定された2つのuint96型の数値を加算します。
加算結果がオーバーフローする場合、エラーメッセージを表示してリバートします。

引数 or パラメータ

  • a
    • 加算する値。
  • b
    • 加算する値。
  • errorMessage
    • エラーメッセージ。

戻り値

  • uint96
    • 加算結果の値。

sub96

sub96
function sub96(
    uint96 a,
    uint96 b,
    string memory errorMessage
) internal pure returns (uint96)

概要
uint96型の2つの数値を減算する関数。

詳細
指定された2つのuint96型の数値を減算します。
減算結果がアンダーフローする場合、エラーメッセージを表示してリバートします。

引数

  • a
    • 減算される値。
  • b
    • 減算する値。
  • errorMessage
    • エラーメッセージ。

戻り値

  • uint96
    • 減算結果の値。

getChainId

getChainId
function getChainId() internal view returns (uint256)

概要
現在のチェーンのチェーンIDを取得関数。

詳細
アセンブリ命令を使用して現在のチェーンのチェーンIDを取得します。

戻り値

  • uint256
    • 現在のチェーンのチェーンID。

イベント

Approval

Approval
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId)

概要
トークン所有者が特定のアドレスに対してトークンの承認をした時に発行されるイベント。

パラメータ

  • owner
    • トークンの所有者のアドレス。
  • approved
    • 承認されたアドレス。
  • tokenId
    • 対象のトークンのID。

ApprovalForAll

ApprovalForAll
event ApprovalForAll(address indexed owner, address indexed operator, bool approved)

概要
トークン所有者が特定のアドレスに対してすべてのトークンの操作を許可または拒否した時に発行されるイベント。

パラメータ

  • owner
    • トークンの所有者のアドレス。
  • operator
    • 操作を行うアドレス。
  • approved
    • 操作の許可(true)または拒否(false)。

DelegateChanged

DelegateChanged
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate)

概要
デリゲートが変更された時に発行されるイベント。

パラメータ

  • delegator
    • デリゲートを変更するアドレス。
  • fromDelegate
    • 変更前のデリゲート先のアドレス。
  • toDelegate
    • 変更後のデリゲート先のアドレス。

DelegateVotesChanged

DelegateVotesChanged
event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance)

概要
デリゲート先の投票数が変更された時に発行されるイベント。

パラメータ

  • delegate
    • デリゲート先のアドレス。
  • previousBalance
    • 変更前の投票数。
  • newBalance
    • 変更後の投票数。

DescriptorLocked

DescriptorLocked
event DescriptorLocked()

概要
トークンURIのディスクリプタがロックされた時に発行されるイベント。


DescriptorUpdated

DescriptorUpdated
event DescriptorUpdated(INounsDescriptor indexed descriptor)

概要
トークンURIのディスクリプタが更新された時に発行されるイベント。

パラメータ

  • INounsDescriptor indexed descriptor
    • 更新後のディスクリプタ。

MinterLocked

MinterLocked
event MinterLocked()

概要
トークンのミンターがロックされた時に発行されるイベント。


MinterUpdated

MinterUpdated
event MinterUpdated(address indexed minter)

概要
トークンのminterが更新された時に発行されるイベント。

パラメータ

  • minter
    • 新しいminterのアドレス。

NounBurned

NounBurned
event NounBurned(uint256 indexed tokenId)

概要
トークンが焼却された時に発行されるイベント。

パラメータ

  • tokenId
    • 焼却されたトークンのID。

NounCreated

NounCreated
event NounCreated(uint256 indexed tokenId, INounsSeeder.Seed seed)

概要
新しいトークンが生成された時に発行されるイベント。

パラメータ

  • tokenId
    • 生成されたトークンのID。
  • INounsSeeder.Seed seed
    • 生成に使用されたシード情報。

NoundersDAOUpdated

NoundersDAOUpdated
event NoundersDAOUpdated(address indexed noundersDAO)

概要
Nounders DAO(デリゲート先)が更新された時に発行されるイベント。

パラメータ

  • noundersDAO
    • 新しいNounders DAO(デリゲート先)のアドレス。

OwnershipTransferred

OwnershipTransferred
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)

概要
トークンのオーナーシップが移転された時に発行されるイベント。

パラメータ

  • previousOwner
    • 移転前のオーナーのアドレス。
  • newOwner
    • 新しいオーナーのアドレス。

SeederLocked

SeederLocked
event SeederLocked()

概要
トークンのシーダーがロックされた時に発行されるイベント。


SeederUpdated

SeederUpdated
event SeederUpdated(INounsSeeder indexed seeder)

概要
トークンのシーダーが更新された時に発行されるイベント。

パラメータ

  • INounsSeeder indexed seeder
    • 新しいシーダーのアドレス。

Transfer

Transfer
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)

概要
トークンの所有権が移転された時に発行されるイベント。

パラメータ

  • from
    • 移転元のアドレス。
  • to
    • 移転先のアドレス。
  • tokenId
    • 移転されたトークンのID。

コード

ベースコントラクト

  • contracts/base

インターフェース

  • /contracts/interfaces

外部コントラクト

  • /contracts/external

最後に

今回の記事では、Bunzzの新機能『DeCipher』を使用して、Nounsの「NounsToken」のコントラクトを見てきました。
いかがだったでしょうか?
今後も特定のNFTやコントラクトをピックアップしてまとめて行きたいと思います。

普段はブログやQiitaでブロックチェーンやAIに関する記事を挙げているので、よければ見ていってください!

https://chaldene.net/

https://qiita.com/cardene

CryptoGames

Discussion