Solidity を使用してオンチェーン NFT を 5 分で作成する方法を学びましょう

オフチェーンNFT
ここで疑問が生じますが、すべての NFT はオンチェーンではないのですか?イーサリアム ブロックチェーン上で NFT を扱ったことがある人なら誰でも、オンチェーン データ ストレージには制限があると言えるでしょう。オンチェーン データ ストレージは非常に高価であり、ほとんどの NFT プロジェクトは画像とメタデータ ファイルをオフチェーンに保存します。多くの場合、「オンチェーン」に保存されている唯一のデータは、メタデータの不変ハッシュ (tokenURI) です。このハッシュを記述する最も簡単な方法は、実際の NFT へのリンクです。ここでの違いは、ハッシュがデータに依存することです。作成し、ソースを変更すると、ハッシュは有効ではなくなるため、不変になります。誰でもブロックチェーン ノード マイナーやコンセンサスを実行できるのと同じように、誰でも IPFS ノードを実行できます。
さて、私たちは Loot のような「オンチェーン」プロジェクトに精通しているかもしれませんが、これはどのように行われるのでしょうか? 実際に適切なビジュアル メディアをオンチェーンに保存できるのでしょうか?
答えは「はい」ですが、Base64 エンコーディングと SVG 画像タイプなど、いくつかのことが必要です。どちらも、PNG や JPEG などの一般的なメモリの「重い」ビジュアル データではなく、テキスト データを扱うことができます。これは、次の 2 つのことを行う必要があることを意味します。
JSON メタデータを Base64 エンコードする
画像レンダリングの「命令」をSVG形式でエンコードする
幸いなことに、ブラウザーは両方の形式を理解しており、OpenSea などのブラウザーベースのマーケットプレイスは、IPFS ストア ハッシュへのリンクと同じ方法で NFT をレンダリングできます。ただし、ブラウザーは画像を「フェッチしてキャッシュする」のではなく、代わりに画像をレンダリングします。
Base64エンコーディング
オンチェーンのメタデータ ストレージを実現し、IPFS などのツールの必要性を回避する 1 つの方法は、メタデータを Base64 でエンコードし、NFT トークン データに直接保存することです。この場合、tokenURI は実際のメタデータをエンコードされた形式で返します。これは「リンク」ではなく、メタデータ自体です。
先ほども述べたように、GitHub の既存の Base64.sol ライブラリを利用します。 github からインポートすることも、単にコードを複製/コピーして、このファイルを貼り付けた同じディレクトリからインポートすることもできます。
Base64 へのエンコードについて注意すべき点は、エンコードはデータ圧縮の形式ではないため、データのサイズを削減するのではなく、ブラウザがデコードできる形式でデータを保存するだけであるということです。 NFT 画像の場合のように、メタデータはそれほど大きくありません。以下に例を示します。

このコード例では、tokenId (NFT の ID) を取得し、その名前、説明、プロパティを使用して OpenSea を含む Base64 でエンコードされた JSON テキスト文字列を返す関数「BuildMetaData」を利用して、NFT に必要なものすべてをレンダリングします。そして非常に重要なのは、私たちのイメージです。また、以下で説明する BuildImage 関数も利用します。
以下はメタデータの例です。
{
"name":"NFT1",
"description":"This is our on-chain NFT",
"image": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAwIiBoZWlnaHQ9IjUwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCBpZD0ic3ZnXzExIiBoZWlnaHQ9IjYwMCIgd2lkdGg9IjUwMyIgeT0iMCIgeD0iMCIgZmlsbD0iaHNsKDI5Myw1MCUsMjUlKSIvPjx0ZXh0IGZvbnQtc2l6ZT0iMTgiIHk9IjEwJSIgeD0iNSUiIGZpbGw9ImhzbCg5MCwxMDAlLDgwJSkiPlNvbWUgVGV4dDwvdGV4dD48dGV4dCBmb250LXNpemU9IjE4IiB5PSIxNSUiIHg9IjUlIiBmaWxsPSJoc2woOTAsMTAwJSw4MCUpIj5Tb21lIFRleHQ8L3RleHQ+PHRleHQgZm9udC1zaXplPSIxOCIgeT0iMjAlIiB4PSI1JSIgZmlsbD0iaHNsKDkwLDEwMCUsODAlKSI+U29tZSBUZXh0PC90ZXh0Pjx0ZXh0IGZvbnQtc2l6ZT0iMTgiIHk9IjEwJSIgeD0iODAlIiBmaWxsPSJoc2woOTAsMTAwJSw4MCUpIj5Ub2tlbjogMTwvdGV4dD48dGV4dCBmb250LXNpemU9IjE4IiB5PSI1MCUiIHg9IjUwJSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iaHNsKDkwLDEwMCUsODAlKSI+dXNlclRleHQ8L3RleHQ+PC9zdmc+",
"attributes": [
{
"trait_type": "TextColor",
"value":"328"
}
]
}
通常、「image」値は次のようになります。
{
"image": "ipfs://QmWwMDLz6hQKCqjYba5cSHdrNUvPvAdndtaWjdFpm52GYm/1.gif"
}
では、画像値はどうなっているのでしょうか? 画像値は 1 - SVG、2 - SVG も Base64 でエンコードされています。これは、SVG テキストが json (テキスト) データのようにエンコードされていることを意味します。
次のように、エンコードされた json にいくつかのコンテンツを追加したことがわかります。
「アプリケーション/json データ:;base64」
これは、データが何であるか、および受信者または受信者のブラウザーがそれに応じてデータをどのようにデコードできるかを簡単に説明します。
ABI エンコーディング
また、プロジェクト コード全体で ABI エンコードも実行します。この例では、ABI エンコードまたはアプリケーション バイナリ インターフェイスでのみ、複数行のテキストを連結できます。 「This」、「is」、「my」、「code」は、単一の文字列にエンコードされていない場合、エラーが発生します。
SVGファイル
SVG とは何ですか?なぜそれが私たちにとって重要なのでしょうか?
SVG またはスケーラブル ベクター グラフィックスでは、基本的に、画像を xml タイプの形式で、またはテキスト (オンチェーンに保存できるテキスト) として保存できます。大きな画像データを保存する代わりに、必要な画像をテキストで記述し、ブラウザと OpenSea がレンダリングできる方法でエンコードします。サイズ、色、さらにはレンダリングできるテキストなど、画像のさまざまな特性を設定できます。
このように考えてください。単純な画像を送りたい場合は、高解像度の PNG 画像を電子メールまたはテキスト メッセージで送信することもできます。あるいは、それを数語で説明して領収書を送信することもできます。送信者がそれをレンダリングまたは生成します。 。データ転送にコストがかかる場合は、(努力として)受信側のコストを増やすことでコストを下げる「トレードオフ」を行うことができます。
以下のテキスト説明は、HD PNG よりも転送にかかるデータ量がはるかに少なくなる可能性があります。受信者がこれを簡単に提示できるツールを持っている限り、データの保存または転送のコストを大幅に削減します。
「500x500 の青い背景に「Hello World」という白い文字」
コード例では、関数 BuildImage 内の SVG のパラメーターを記述しています。
SVG を生成するための優れたオンライン ツールやテンプレートは数多くありますので、アイデアを SVG に変換するのに役立つものを見つけることをお勧めします。
アプリ開発で「ハードコーディングされた」値は、レンダリングされる画面サイズを増減するときに問題を引き起こす可能性があるため、レイアウトには必ずパーセンテージを使用してください。デバイスの画面サイズを 1000x1000 未満に縮小するまでは、テキストの開始点として 1000 ピクセルで問題ありません。その場合は、80% に設定することをお勧めします。
ABI および Base64 エンコード前の SVG:
'
""
データに関する詳細が添付されていることが再度わかります。
“data:image/svg+xml;base64”
ユーザー入力
私たちのスマートコントラクトのより興味深い機能の 1 つは、ユーザーがテキストデータを mint 関数に入力することで最終的な NFT に貢献できることです。このユーザー入力は「メモリ内の文字列」として保存され、BuildImage 関数を介して SVG データに動的に追加されます。
テキスト入力のサイズを制限し、この制限に対するエラーを追加しましたが、ユーザーは何を追加する可能性があるかを十分に認識しています。これは不変であり、ブロックチェーン上に永久に存在します。
mint 関数は、関数に文字列の期待値を追加することでこれを行います。
function mint(string memory _userText) public payable {
uint256 supply = totalSupply();
bytes memory strBytes = bytes(_userText);
require(strBytes.length <= stringLimit, "String input exceeds limit.");
require(exists(_userText) != true, "String already exists!");
Word memory newWord = Word(
string(
abi.encodePacked(
"NFT",
uint256(supply + 1).toString()
)
),
"This is our on-chain NFT",
randomNum(361, block.difficulty, supply).toString(),
randomNum(361, block.timestamp, supply).toString(),
_userText
);
if (msg.sender != owner()) {
require(msg.value >= 0.005 ether);
}
wordsToTokenId[supply + 1] = newWord; //Add word to mapping @tokenId
_safeMint(msg.sender, supply + 1);
NFTとスマートコントラクトの相互作用
Remix などのツールを使用している場合は、提供されたコードを変更して Remix にアップロードし、コンパイルしてテスト用にデプロイするだけです。
mint 関数では、ユーザーが文字列データを入力し、テキストを追加できるようにしてから、tokenURI 関数を利用して生成されたものを確認する必要があるため、これは OpenSea などのマーケットプレイスが NFT データを取得または解析するために利用するものと同じ tokenURI 関数です。画像。

では、どうすればよいのでしょうか? ブラウザでレンダリングするには、「string」以降のすべてをコピーし (これは必要ありません)、ブラウザに貼り付ける必要があります。これをブラウザに貼り付けると、結果は次のようになります。

さらに、「image」値をコピーすることで画像を表示できます。コピーしたい部分がここで強調表示されています。

結果は次のようになります。

画像データはローカルブラウザに貼り付けられます
当社のNFT
元のリンク



