[Bunzz Decipher] Nounsの『NounsDescriptor』コントラクトを理解しよう!
はじめに
初めまして。
CryptoGamesというブロックチェーンゲーム企業でエンジニアをしている cardene(かるでね) です!
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。
代表的なゲームはクリプトスペルズというブロックチェーンゲームです。
今回はBunzzの新機能『DeCipher』を使用して、Nounsの「NounsDescriptor」コントラクトを見てみようと思います。
『DeCipher』はAIを使用してコントラクトのドキュメントを自動生成してくれるサービスです。
詳しい使い方に関しては以下の記事を参考にしてください!
今回使用する『DeCipher』のリンクは以下になります。
Etherscanのリンクは以下になります。
概要
NounsDescriptorコントラクトは、Ethereumブロックチェーン上の大規模なシステムの重要なコントラクトです。
このシステムは非代替トークン(NFT)とやり取りするために設計されており、物理的なアイテムのように購入、販売、所有できる一意なデジタルアセットです。
NounsDescriptorコントラクトの目的
各NFTの詳細な説明を提供することです。
これには、NFTの外見に関する情報が含まれます。
たとえば、カラーパレット、背景、ボディ、アクセサリー、頭部などが詳細に記述されます。
また、新しいパーツの追加の可否や、トークンのURI(Uniform Resource Identifier)がデータURIとして返されるかどうかについての情報も管理されます。
さらに、NounsDescriptorコントラクトは、NFTを識別しアクセスするための基盤であるベースURIを管理します。
ベースURIは各NFTの識別子の基本部分を構成する文字列で、これによりNFTがブロックチェーン上で特定されます。
NounsDescriptorコントラクトの仕組み
NounsDescriptorコントラクトは、変数やマッピングといったデータ構造を使用して、各NFTに関連する情報を保存・管理します。
たとえば、カラーパレットに関する情報はマッピングに、背景、ボディ、アクセサリー、頭部に関する情報は配列に格納されます。
また、関数は特定のタスクを実行するためのコードの断片で、例えばベースURIや特定NFTのカラーパレットを取得するための関数があります。
NounsDescriptorコントラクトの重要性
NounsDescriptorコントラクトは、NFTシステムの運用において重要な役割を果たします。
各NFTの詳細な説明を提供することで、ユーザーはNFTのユニークな特徴を理解し、魅力を感じることができます。
また、ベースURIや他の重要なデータを管理することで、NounsDescriptorコントラクトはNFTを正確に識別し、ブロックチェーン上で見つけることができるようにします。
関連リンク
- NounsAuctionHouse on Etherscan
- NounsDAOExecutor on Etherscan
- NounsDAOProxy on Etherscan
- GovernorBravoDelegator on Etherscan
- Official website for Nouns
使い方
コントラクトの目標
NounsDescriptorコントラクトは、Nounsトークンに関する詳細な説明を提供することを目的としています。Nounsプロジェクトは、1日に1つのNoun(NFT)を生成する分散型自治組織(DAO)の一部です。
コントラクトの使用手順
1. コントラクトのデプロイ
まず、NounsDescriptorコントラクトをEthereumネットワークにデプロイします。
これは、コントラクトをブロックチェーン上に展開するプロセスです。
TruffleやHardhatなどの開発ツールを使用して、このデプロイを行います。
2. tokenURI関数の呼び出し
コントラクトがデプロイされたら、tokenURI
関数を呼び出すことで、特定のNounトークンのURIを取得できます。
トークンIDを引数として指定し、そのトークンに関連するURI(Uniform Resource Identifier)を取得します。
これにより、そのNFTの詳細情報を取得する際に利用できます。
3. dataURI関数の呼び出し
特定のNounトークンのデータURIを取得するためには、dataURI
関数を使用します。
同様に、トークンIDを引数として渡すことで、そのNFTのデータURIを取得します。
データURIは、NFTの詳細データを表すもので、画像やメタデータなどが含まれます。
4. tokenSVG関数の呼び出し
もし特定のNounトークンのSVG表現を取得したい場合は、tokenSVG
関数を呼び出します。
この関数もトークンIDを引数として渡すことで、そのNFTのSVG表現を取得します。
SVGはベクトル形式の画像表現であり、NFTの外観を表示するのに役立ちます。
これらの手順に従うことで、NounsDescriptorコントラクトを活用することができます。
各Nounトークンに関する詳細情報や、URI、データURI、SVG表現を取得するための基本的なステップです。
これにより、開発者はNFTのデータや表示に関する情報を効果的に利用できます。
Note
このガイドは、Ethereumやスマートコントラクト、Solidityプログラミング言語に基本的な理解があることを前提としています。
上記が初めての場合は、進む前にそれらについて学習しておくことをおすすめします。
また、NounsDescriptorコントラクトは広範なコントラクトのエコシステムの一部です。
その機能を完全に理解するためには、Nounsプロジェクト内の他のコントラクトも調べることが重要です。
コントラクト
NounsDescriptor
COPYRIGHT_CC0_1_0_UNIVERSAL_LICENSE
bytes32 constant COPYRIGHT_CC0_1_0_UNIVERSAL_LICENSE = 0xa2010f343487d3f7618affe54f789f5487602331c0a8d03f49e9a7c547cf0499;
概要
Creative Commons CC0 1.0 パブリックドメイン宣言のテキストのハッシュを表します。
詳細
0xa2010f343487d3f7618affe54f789f5487602331c0a8d03f49e9a7c547cf0499
という値は、Creative Commons CC0 1.0 パブリックドメイン宣言 のテキストのハッシュです。
arePartsLocked
bool public override arePartsLocked;
概要
新しいNounパーツが追加可能かどうかを示すブール値。
詳細
true
の場合、新しいパーツの追加はできません。
false
の場合、新しいパーツを追加できます。
isDataURIEnabled
bool public override isDataURIEnabled = true;
概要
tokenURI
がデータURIとして返されるかどうかを示すブール値。
詳細
true
の場合、データURIとして返されます。
false
の場合、通常のURLとして返されます。
baseURI
string public override baseURI;
概要
トークンのメタデータのベースURIを示す文字列。
詳細
トークンのメタデータ(画像など)のベースとなるURIを示します。
トークンごとの識別子などが後に続き、完全なメタデータのURLを構築します。
palettes
mapping(uint8 => string[]) public override palettes;
概要
Nounカラーパレットを格納するマッピング配列。
詳細
この変数は、Nounの異なるパーツに対するカラーパレットを格納するためのマッピングです。uint8
型のインデックスに対して、対応するカラーコードの文字列配列が格納されます。
backgrounds
string[] public override backgrounds;
概要
Nounの背景色(ヘックスカラーコード)を格納する配列。
詳細
Nounの背景色に関する情報を格納するための配列です。
背景色はhex
カラーコードで表されます。
bodies
bytes[] public override bodies;
概要
Nounのボディ部分のカスタムRun-Length Encoding(RLE) データを格納する配列。
詳細
Nounのボディ部分のカスタムRLEデータを格納するための配列です。
異なるボディのデザインが格納されます。
accessories
bytes[] public override accessories;
概要
Nounのアクセサリ部分のカスタムRun-Length Encoding(RLE) データを格納する配列。
詳細
この変数は、Nounのアクセサリ部分のカスタムRLEデータを格納するための配列。
異なるアクセサリのデザインが格納されます。
heads
bytes[] public override heads;
概要
Nounのヘッド部分のカスタムRun-Length Encoding(RLE) データを格納する配列。
詳細
Nounのヘッド部分のカスタムRLEデータを格納するための配列です。
異なるヘッドのデザインが格納されます。
glasses
bytes[] public override glasses;
概要
Nounのメガネ部分のカスタムRun-Length Encoding(RLE) データを格納する配列。
詳細
Nounのメガネ部分のカスタムRLEデータを格納するための配列です。異なるメガネのデザインが格納されます。
whenPartsNotLocked
modifier whenPartsNotLocked() {
require(!arePartsLocked, 'Parts are locked');
_;
}
概要
パーツがロックされていないことを確認する修飾子。
詳細
この修飾子は、関数の実行前に呼び出され、arePartsLocked
変数がfalse
(ロックされていない)ことを確認します。
もし変数がtrue
の場合、'Parts are locked' というエラーメッセージとともに関数の実行が中断されます。
backgroundCount
backgroundCount
function backgroundCount() external view override returns (uint256) {
return backgrounds.length;
}
概要
Nounの「backgrounds
」の利用可能な数を取得する関数。
戻り値
-
uint256
- 利用可能なNoun背景の数。
bodyCount
bodyCount
function bodyCount() external view override returns (uint256) {
return bodies.length;
}
概要
Nounの「bodies
」の利用可能な数を取得する関数。
戻り値
-
uint256
- 利用可能なNoun体の数。
accessoryCount
accessoryCount
function accessoryCount() external view override returns (uint256) {
return accessories.length;
}
概要
Nounの「accessories
」の利用可能な数を取得する関数。
戻り値
-
uint256
- 利用可能なNounアクセサリの数。
headCount
:::details
function headCount() external view override returns (uint256) {
return heads.length;
}
:::
概要
Nounの「heads
」の利用可能な数を取得する関数。
戻り値
-
uint256
- 利用可能なNoun頭部の数。
glassesCount
glassesCount
function glassesCount() external view override returns (uint256) {
return glasses.length;
}
概要
Nounの「glasses
」の利用可能な数を取得する関数。
戻り値
-
uint256
- 利用可能なNoun眼鏡の数。
addManyColorsToPalette
addManyColorsToPalette
function addManyColorsToPalette(uint8 paletteIndex, string[] calldata newColors) external override onlyOwner {
require(palettes[paletteIndex].length + newColors.length <= 256, 'Palettes can only hold 256 colors');
for (uint256 i = 0; i < newColors.length; i++) {
_addColorToPalette(paletteIndex, newColors[i]);
}
}
概要
カラーパレットに色を追加する関数。
詳細
この関数はオーナーによって呼び出されることができ、指定したカラーパレットに複数の色を追加します。
パレットのインデックスと新しい色の配列を引数として受け取り、追加される色の合計が256
色以下であることを確認します。
引数
-
paletteIndex
- カラーパレットのインデックス。
-
newColors
- 追加する色の配列。
戻り値
なし
addManyBackgrounds
addManyBackgrounds
function addManyBackgrounds(string[] calldata _backgrounds) external override onlyOwner whenPartsNotLocked {
for (uint256 i = 0; i < _backgrounds.length; i++) {
_addBackground(_backgrounds[i]);
}
}
概要
複数のNoun背景を一括追加する関数。
詳細
この関数はオーナーによって、ロックされていない状態で呼び出されることができます。
与えられたNoun背景の配列を順番に追加します。
引数
-
_backgrounds
- 追加するNoun背景の配列。
戻り値
なし
addManyBodies
addManyBodies
function addManyBodies(bytes[] calldata _bodies) external override onlyOwner whenPartsNotLocked {
for (uint256 i = 0; i < _bodies.length; i++) {
_addBody(_bodies[i]);
}
}
概要
複数のNounのボディーを一括追加する関数。
引数
-
_bodies
- 追加するNounのボディーのバイト列の配列。
戻り値
なし
addManyAccessories
addManyAccessories
function addManyAccessories(bytes[] calldata _accessories) external override onlyOwner whenPartsNotLocked {
for (uint256 i = 0; i < _accessories.length; i++) {
_addAccessory(_accessories[i]);
}
}
概要
複数のNounアクセサリを一括追加する関数。
引数
-
_accessories
- 追加するNounアクセサリのバイト列の配列。
戻り値
なし
addManyHeads
addManyHeads
function addManyHeads(bytes[] calldata _heads) external override onlyOwner whenPartsNotLocked {
for (uint256 i = 0; i < _heads.length; i++) {
_addHead(_heads[i]);
}
}
概要
複数のNoun頭部を一括追加する関数。
引数
-
_heads
- 追加するNoun頭部のバイト列の配列。
戻り値
なし
addManyGlasses
addManyGlasses
function addManyGlasses(bytes[] calldata _glasses) external override onlyOwner whenPartsNotLocked {
for (uint256 i = 0; i < _glasses.length; i++) {
_addGlasses(_glasses[i]);
}
}
概要
複数のNoun眼鏡を一括追加する関数。
引数
-
_glasses
- 追加するNoun眼鏡のバイト列の配列。
戻り値
なし
addColorToPalette
addColorToPalette
function addColorToPalette(uint8 _paletteIndex, string calldata _color) external override onlyOwner {
require(palettes[_paletteIndex].length <= 255, 'Palettes can only hold 256 colors');
_addColorToPalette(_paletteIndex, _color);
}
概要
カラーパレットに単一の色を追加する関数。
詳細
この関数はオーナーによって呼び出され、指定したカラーパレットに単一の色を追加します。
パレットのインデックスと追加する色の文字列を引数として受け取り、パレットが256
色以下の色を保持することを確認します。
引数
-
_paletteIndex
- カラーパレットのインデックス。
-
_color
- 追加する色の文字列。
戻り値
なし
addBackground
addBackground
function addBackground(string calldata _background) external override onlyOwner whenPartsNotLocked {
_addBackground(_background);
}
概要
Nounの背景を追加する関数。
詳細
オーナーによって呼び出され、ロックされていない状態でNounの背景を追加します。
引数
-
_background
- 追加するNoun背景の文字列。
戻り値
なし
addBody
addBody
function addBody(bytes calldata _body) external override onlyOwner whenPartsNotLocked {
_addBody(_body);
}
概要
Nounのボディーを追加する関数。
詳細
この関数はオーナーによって呼び出され、ロックされていない状態でNounのボディーを追加します。
引数
-
_body
- 追加するNounのボディーのバイト列。
戻り値
なし
addAccessory
addAccessory
function addAccessory(bytes calldata _accessory) external override onlyOwner whenPartsNotLocked {
_addAccessory(_accessory);
}
概要
Nounのアクセサリを追加する関数。
詳細
この関数はオーナーによって呼び出され、ロックされていない状態でNounのアクセサリを追加します。
引数
-
_accessory
- 追加するNounアクセサリのバイト列。
戻り値
なし
addHead
addHead
function addHead(bytes calldata _head) external override onlyOwner whenPartsNotLocked {
_addHead(_head);
}
概要
Nounの頭部を追加する関数。
詳細
この関数はオーナーによって呼び出され、ロックされていない状態でNounの頭部を追加します。
引数
-
_head
- 追加するNoun頭部のバイト列。
戻り値
なし
addGlasses
addGlasses
function addGlasses(bytes calldata _glasses) external override onlyOwner whenPartsNotLocked {
_addGlasses(_glasses);
}
概要
Nounの眼鏡を追加する関数。
詳細
この関数はオーナーによって呼び出され、ロックされていない状態でNounの眼鏡を追加します。
引数
-
_glasses
- 追加するNoun眼鏡のバイト列。
戻り値
なし
lockParts
lockParts
function lockParts() external override onlyOwner whenPartsNotLocked {
arePartsLocked = true;
emit PartsLocked();
}
概要
すべてのNounパーツをロックする関数。
詳細
この関数はオーナーによって呼び出され、ロックされていない状態ですべてのNounパーツをロックします。
一度ロックすると元に戻すことはできません。
戻り値
なし
toggleDataURIEnabled
toggleDataURIEnabled
function toggleDataURIEnabled() external override onlyOwner {
bool enabled = !isDataURIEnabled;
isDataURIEnabled = enabled;
emit DataURIToggled(enabled);
}
概要
tokenURI
がデータURIかHTTP URLを返すかを切り替える関数。
詳細
この関数はオーナーによって呼び出され、tokenURI
が返す値がデータURIかHTTP URLかを切り替えます。
戻り値
なし
setBaseURI
setBaseURI
function setBaseURI(string calldata _baseURI) external override onlyOwner {
baseURI = _baseURI;
emit BaseURIUpdated(_baseURI);
}
概要
すべてのトークンIDのベースURIを設定する関数。
詳細
この関数はオーナーによって呼び出され、tokenURI
で返される値に自動的に接頭辞が付加されます。
引数
-
_baseURI
- ベースURI。
戻り値
なし
tokenURI
tokenURI
function tokenURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view override returns (string memory) {
if (isDataURIEnabled) {
return dataURI(tokenId, seed);
}
return string(abi.encodePacked(baseURI, tokenId.toString()));
}
概要
公式のNouns DAOのNounsのためのトークンURIを生成する関数。
詳細
与えられたトークンIDとシードを使用して、トークンURIを生成します。
isDataURIEnabled
が有効な場合、データURIを生成し、それ以外の場合はHTTP URLを生成します。
引数
-
tokenId
- トークンID。
-
INounsSeeder.Seed memory seed
- シード情報。
戻り値
-
memory
- 生成されたトークンURI。
dataURI
dataURI
function dataURI(uint256 tokenId, INounsSeeder.Seed memory seed) public view override returns (string memory) {
string memory nounId = tokenId.toString();
string memory name = string(abi.encodePacked('Noun ', nounId));
string memory description = string(abi.encodePacked('Noun ', nounId, ' is a member of the Nouns DAO'));
return genericDataURI(name, description, seed);
}
概要
与えられたトークンIDとシード(seed
)に基づいて、公式のNouns DAOのNounのbase64エンコードされたデータURIを構築する関数。
詳細
与えられたトークンIDとシード(seed
)から名前と説明を生成し、genericDataURI
関数を呼び出してデータURIを構築します。
引数
-
tokenId
- トークンのID。
-
INounsSeeder.Seed memory seed
- シード情報。
戻り値
-
string memory
- base64エンコードされたデータURI。
genericDataURI
genericDataURI
function genericDataURI(
string memory name,
string memory description,
INounsSeeder.Seed memory seed
) public view override returns (string memory) {
NFTDescriptor.TokenURIParams memory params = NFTDescriptor.TokenURIParams({
name: name,
description: description,
parts: _getPartsForSeed(seed),
background: backgrounds[seed.background]
});
return NFTDescriptor.constructTokenURI(params, palettes);
}
概要
与えられた名前、説明、およびシード(seed
)に基づいて、base64エンコードされたデータURIを構築する関数。
詳細
名前、説明、およびシード(seed
)を受け取り、それらの情報を使ってNFTDescriptor.TokenURIParams
を生成し、constructTokenURI
関数を呼び出してデータURIを構築します。
引数
-
name
- 名前。
-
description
- 説明。
-
INounsSeeder.Seed memory seed
- シード情報。
戻り値
-
string memory
- base64エンコードされたデータURI。
generateSVGImage
generateSVGImage
function generateSVGImage(INounsSeeder.Seed memory seed) external view override returns (string memory) {
MultiPartRLEToSVG.SVGParams memory params = MultiPartRLEToSVG.SVGParams({
parts: _getPartsForSeed(seed),
background: backgrounds[seed.background]
});
return NFTDescriptor.generateSVGImage(params, palettes);
}
概要
与えられたシード(seed
)に基づいて、base64エンコードされたSVG画像を構築する関数。
詳細
この関数は、シード(seed
)を受け取り、それを使ってMultiPartRLEToSVG.SVGParams
を生成し、generateSVGImage
関数を呼び出してSVG画像を構築します。
引数
-
INounsSeeder.Seed memory seed
- シード情報。
戻り値
-
string memory
- base64エンコードされたSVG画像。
_addColorToPalette
_addColorToPalette
function _addColorToPalette(uint8 _paletteIndex, string calldata _color) internal {
palettes[_paletteIndex].push(_color);
}
概要
カラーパレットに単一の色を追加する関数。
詳細
与えられたパレットインデックスと色を使って、カラーパレットに色を追加します。
引数
-
_paletteIndex
- パレットのインデックス。
-
_color
- 追加する色。
戻り値
なし
_addBackground
_addBackground
function _addBackground(string calldata _background) internal {
backgrounds.push(_background);
}
概要
Nounの背景を追加する関数。
詳細
与えられた背景を背景リストに追加します。
引数
-
_background
- 追加する背景。
戻り値
なし
_addBody
_addBody
function _addBody(bytes calldata _body) internal {
bodies.push(_body);
}
概要
Nounのボディーを追加します。
詳細
与えられたNounのボディーをボディーリストに追加します。
引数
-
_body
- 追加するボディーのバイト列。
戻り値
なし
_addAccessory
_addAccessory
function _addAccessory(bytes calldata _accessory) internal {
accessories.push(_accessory);
}
概要
Nounのアクセサリを追加します。
詳細
与えられたアクセサリをアクセサリリストに追加します。
引数
-
_accessory
- 追加するアクセサリのバイト列。
戻り値
なし
_addHead
_addHead
function _addHead(bytes calldata _head) internal {
heads.push(_head);
}
概要
Nounの頭部を追加する関数。
詳細
与えられた頭部を頭部リストに追加します。
引数
-
_head
- 追加する頭部のバイト列。
戻り値
なし
_addGlasses
tokenURI
function _addGlasses(bytes calldata _glasses) internal {
glasses.push(_glasses);
}
概要
Nounの眼鏡を追加する関数。
詳細
与えられた眼鏡を眼鏡リストに追加します。
引数
-
_glasses
- 追加する眼鏡のバイト列。
戻り値
なし
_getPartsForSeed
tokenURI
function _getPartsForSeed(INounsSeeder.Seed memory seed) internal view returns (bytes[] memory) {
bytes[] memory _parts = new bytes[](4);
_parts[0] = bodies[seed.body];
_parts[1] = accessories[seed.accessory];
_parts[2] = heads[seed.head];
_parts[3] = glasses[seed.glasses];
return _parts;
}
概要
与えられたシード(seed
)に対応するすべてのNounパーツを取得する関数。
詳細
与えられたシード(seed
)を使って、対応するNounのボディー、アクセサリ、頭部、眼鏡のパーツを取得します。
引数
-
INounsSeeder.Seed memory seed
- シード情報。
戻り値
-
bytes[] memory
- パーツのバイト列の配列。
NFTDescriptor
TokenURIParams
TokenURIParams
struct TokenURIParams {
string name;
string description;
bytes[] parts;
string background;
}
概要
ERC721トークンのURIを構築するためのパラメータを保持する構造体。
パラメータ
-
name
- ークンの名前を示す文字列。
-
description
- トークンの説明を示す文字列。
-
parts
- トークンを構成するパーツのバイト列の配列。
-
background
- トークンの背景を示す文字列。
constructTokenURI
constructTokenURI
function constructTokenURI(TokenURIParams memory params, mapping(uint8 => string[]) storage palettes)
public
view
returns (string memory)
{
string memory image = generateSVGImage(
MultiPartRLEToSVG.SVGParams({ parts: params.parts, background: params.background }),
palettes
);
// prettier-ignore
return string(
abi.encodePacked(
'data:application/json;base64,',
Base64.encode(
bytes(
abi.encodePacked('{"name":"', params.name, '", "description":"', params.description, '", "image": "', 'data:image/svg+xml;base64,', image, '"}')
)
)
)
);
}
ERC721トークンのURIを構築する関数。
詳細
与えられたTokenURIParams
およびパレット情報を基に、トークンのURIを構築します。
トークンの名前、説明、パーツ、および背景情報から、JSON形式のメタデータを生成し、それをBase64エンコードしてURIを完成させます。
引数
-
params
-
ERC721トークンのメタデータパラメータを保持する
TokenURIParams
構造体。
-
ERC721トークンのメタデータパラメータを保持する
-
palettes
- パーツのパレット情報を保持するマッピング配列。
戻り値
生成されたトークンのURIを文字列として返します。
generateSVGImage
generateSVGImage
function generateSVGImage(MultiPartRLEToSVG.SVGParams memory params, mapping(uint8 => string[]) storage palettes)
public
view
returns (string memory svg)
{
return Base64.encode(bytes(MultiPartRLEToSVG.generateSVG(params, palettes)));
}
概要
ERC721トークンのURIに含まれるSVG画像を生成する関数。
詳細
与えられたSVGParams
およびパレット情報を基に、複数のパーツを組み合わせたSVG画像を生成します。
具体的には、MultiPartRLEToSVG.generateSVG
関数を呼び出してSVG画像を生成し、それをBase64エンコードして返します。
引数
-
params
- SVG画像の生成に必要なパラメータを保持する
SVGParams
構造体。
- SVG画像の生成に必要なパラメータを保持する
-
palettes
- パーツのパレット情報を保持するマッピング配列。
戻り値
生成されたSVG画像をBase64エンコードして文字列として返します。
MultiPartRLEToSVG
SVGParams
SVGParams
struct SVGParams {
bytes[] parts;
string background;
}
概要
SVGイメージを生成する際のパラメータを格納する構造体。
詳細
SVGイメージの生成に必要な情報を保持します。
parts
はRLE形式の画像パーツをバイト配列として格納し、background
はSVGイメージの背景色を文字列として保持します。
パラメータ
-
parts
- RLE形式の画像パーツを格納したバイト配列。
-
background
- SVGイメージの背景色を表す文字列。
ContentBounds
ContentBounds
struct ContentBounds {
uint8 top;
uint8 right;
uint8 bottom;
uint8 left;
}
概要
コンテンツの境界情報を格納する構造体。
詳細
コンテンツ内の図形が配置される範囲を示す情報を保持します。
パラメータ
-
top
- コンテンツの上端位置。
-
right
- コンテンツの右端位置。
-
bottom
- コンテンツの下端位置。
-
left
- コンテンツの左端位置。
Rect
Rect
struct Rect {
uint8 length;
uint8 colorIndex;
}
概要
矩形の情報を格納する構造体。
詳細
矩形の長さとカラーインデックスを保持します。
パラメータ
-
length
- 矩形の長さ。
-
colorIndex
- 矩形のカラーインデックス。
DecodedImage
DecodedImage
struct DecodedImage {
uint8 paletteIndex;
ContentBounds bounds;
uint256 width;
Rect[] rects;
}
概要
RLE形式で圧縮された画像をデコードした情報を格納する構造体。
パラメータ
-
paletteIndex
- パレットのインデックス。
-
bounds
- コンテンツの範囲。
-
width
- 画像の幅。
-
rects
- 画像を構成する各矩形の情報。
generateSVG
generateSVG
function generateSVG(SVGParams memory params, mapping(uint8 => string[]) storage palettes)
internal
view
returns (string memory svg)
{
// prettier-ignore
return string(
abi.encodePacked(
'<svg width="320" height="320" viewBox="0 0 320 320" xmlns="http://www.w3.org/2000/svg" shape-rendering="crispEdges">',
'<rect width="100%" height="100%" fill="#', params.background, '" />',
_generateSVGRects(params, palettes),
'</svg>'
)
);
}
概要
RLE画像パーツとカラーパレットを組み合わせて単一のSVGイメージを生成する関数。
詳細
与えられたRLE画像パーツとカラーパレットを用いて、指定された背景色を持つSVGイメージを生成します。
SVGの<rect>
要素と_generateSVGRects
関数から得られるSVG rectsを結合して完成されたSVGイメージを生成します。
引数
-
params
- SVGイメージ生成に必要なパラメータを格納する
SVGParams
構造体。
- SVGイメージ生成に必要なパラメータを格納する
-
palettes
- カラーパレットのマッピング配列。
戻り値
生成されたSVGイメージを表す文字列。
_generateSVGRects
_generateSVGRects
function _generateSVGRects(SVGParams memory params, mapping(uint8 => string[]) storage palettes)
private
view
returns (string memory svg)
{
string[33] memory lookup = [
'0', '10', '20', '30', '40', '50', '60', '70',
'80', '90', '100', '110', '120', '130', '140', '150',
'160', '170', '180', '190', '200', '210', '220', '230',
'240', '250', '260', '270', '280', '290', '300', '310',
'320'
];
string memory rects;
for (uint8 p = 0; p < params.parts.length; p++) {
DecodedImage memory image = _decodeRLEImage(params.parts[p]);
string[] storage palette = palettes[image.paletteIndex];
uint256 currentX = image.bounds.left;
uint256 currentY = image.bounds.top;
uint256 cursor;
string[16] memory buffer;
string memory part;
for (uint256 i = 0; i < image.rects.length; i++) {
Rect memory rect = image.rects[i];
if (rect.colorIndex != 0) {
buffer[cursor] = lookup[rect.length]; // width
buffer[cursor + 1] = lookup[currentX]; // x
buffer[cursor + 2] = lookup[currentY]; // y
buffer[cursor + 3] = palette[rect.colorIndex]; // color
cursor += 4;
if (cursor >= 16) {
part = string(abi.encodePacked(part, _getChunk(cursor, buffer)));
cursor = 0;
}
}
currentX += rect.length;
if (currentX - image.bounds.left == image.width) {
currentX = image.bounds.left;
currentY++;
}
}
if (cursor != 0) {
part = string(abi.encodePacked(part, _getChunk(cursor, buffer)));
}
rects = string(abi.encodePacked(rects, part));
}
return rects;
}
概要
RLE画像パーツとカラーパレットを用いてSVG rectsを生成する関数。
詳細
与えられたRLE画像パーツとカラーパレットを使用して、SVGの<rect>
要素を生成します。
各矩形の情報を元にSVG rectsを生成し、それらを結合して返します。
引数
-
params
- SVGイメージ生成に必要なパラメータを格納する
SVGParams
構造体。
- SVGイメージ生成に必要なパラメータを格納する
-
palettes
- カラーパレットのマッピング配列。
戻り値
生成されたSVG rectsを表す文字列。
_getChunk
_getChunk
function _getChunk(uint256 cursor, string[16] memory buffer) private pure returns (string memory) {
string memory chunk;
for (uint256 i = 0; i < cursor; i += 4) {
chunk = string(
abi.encodePacked(
chunk,
'<rect width="', buffer[i], '" height="10" x="', buffer[i + 1], '" y="', buffer[i + 2], '" fill="#', buffer[i + 3], '" />'
)
);
}
return chunk;
}
概要
提供されたbuffer
内のすべての矩形から成る文字列を返す関数。
詳細
与えられたbuffer
内の矩形の情報を元に、各矩形をSVGの<rect>
要素として生成し、それらを結合して文字列として返します。
引数
-
cursor
- 現在のカーソル位置を示す整数。
-
buffer
- 矩形情報を保持する文字列の配列。
戻り値
すべての矩形から成るSVGの文字列。
_decodeRLEImage
_decodeRLEImage
function _decodeRLEImage(bytes memory image) private pure returns (DecodedImage memory) {
uint8 paletteIndex = uint8(image[0]);
ContentBounds memory bounds = ContentBounds({
top: uint8(image[1]),
right: uint8(image[2]),
bottom: uint8(image[3]),
left: uint8(image[4])
});
uint256 width = bounds.right - bounds.left;
uint256 cursor;
Rect[] memory rects = new Rect[]((image.length - 5) / 2);
for (uint256 i = 5; i < image.length; i += 2) {
rects[cursor] = Rect({ length: uint8(image[i]), colorIndex: uint8(image[i + 1]) });
cursor++;
}
return DecodedImage({ paletteIndex: paletteIndex, bounds: bounds, width: width, rects: rects });
}
概要
単一のRLE圧縮画像をDecodedImage
としてデコードする関数。
詳細
与えられたRLE圧縮画像データを解読し、DecodedImage
構造体として結果を返します。
画像のパレットインデックス、コンテンツの範囲、幅、および各矩形の情報を復元します。
引数
-
image
- RLE圧縮画像を表すバイト配列。
戻り値
DecodedImage
構造体。
イベント
PartsLocked
PartsLocked
event PartsLocked();
概要
パーツがロックされた時に発行されるイベント。
DataURIToggled
DataURIToggled
event DataURIToggled(bool enabled);
概要
Data URIが有効に切り替えられた時に発行されるイベント。
パラメータ
-
enabled
-
Data URIが有効になった場合は
true
、無効になった場合はfalse
。
-
Data URIが有効になった場合は
BaseURIUpdated
BaseURIUpdated
event BaseURIUpdated(string baseURI);
概要
ベースURIが更新された時に発行されるイベント。
パラメータ
-
baseURI
- 更新されたベースURIを表す文字列。
コード
インターフェース
/contracts/interfaces/
ライブラリ
/contracts/libs/
最後に
今回の記事では、Bunzzの新機能『DeCipher』を使用して、Nounsの「NounsDescriptor」のコントラクトを見てきました。
いかがだったでしょうか?
今後も特定のNFTやコントラクトをピックアップしてまとめて行きたいと思います。
普段はブログやQiitaでブロックチェーンやAIに関する記事を挙げているので、よければ見ていってください!
Discussion