Mintverse 合約結構

大綱 - Overview

合約系統結構 - Contract Structure

風險披露聲明 - Risk Disclosure

未來優化方向 - Future Work

合約地址 - Contract Address

去中心化資料庫 - Arweave Mapping Database URI


合約系統結構 - Contract Structure

contracts
├── MintverseDictionary.sol
├── MintverseWord.sol
├── interfaces
│   ├── IMintverseDictionary.sol
│   ├── IMintverseWord.sol
│   └── IWord.sol
└── libraries
    └── ERC721A.sol

本次 NFT 為第一本上鏈的中文辭典,整個合約系統包含了兩個合約 MintverseWord.sol 以及 MintverseDictionary.sol。第一階段,將讓鑄造者們 mint 出 MintverseWord - MVW Token,並同時選擇是否加購 MintverseDictionary - MVD Token。而第二階段我們將進行快照並空投 MintverseDictionary - MVD Token 給有加購的鑄造者。

ERC721A

本次的兩份合約皆繼承 ERC721A。ERC721A 是目前 NFT 圈中最常見,也是經過最多測試的 ERC721 延伸協議,最初由 NFT 項目 Azuki 發布,改進的方向是為了降低批量 Mint 時的 Gas Fee 所開發出來的協議,節省智能合約在鏈上寫入資料的工作。以往的標準較多使用 OpenZeppelin 所發佈的 ERC721 Enumerable,但 Mint 時需要一個個紀錄 Token 所有者,因此 Gas Fee 將會成倍數上升,而 ERC721A 則改由紀錄每次 Mint 時的起始編號,來改變需要一個一個 Mint的限制。而 ERC721A 也在團隊完成發行之後交由工程團隊 Chiru Labs 維護。以下為官方文件中有關於 Gas 的比較與介紹連結:

Gas used: ERC721 Enumerable v.s. ERC721A
Gas used: ERC721 Enumerable v.s. ERC721A
Gas Fee(in USD): ERC721 Enumerable v.s. ERC721A
Gas Fee(in USD): ERC721 Enumerable v.s. ERC721A

https://www.erc721a.org/

MintverseWord.sol

Metadata 上鏈

MintverseWord Token 將會紀錄與詞彙相關的 Metadata。每一個詞彙一共會包含九個部分,分別是鑄造者 definerPart、關係詞 relatedWordPart、註釋 descriptionPart、詞彙 wordPart、詞彙類別 categoryPart、詞性一 partOfSpeechPart1、詞性二 partOfSpeechPart2、詞彙倒數起始時間 mintTime、是否定義 defined。

每個 token 所會儲存在鏈上的資料
每個 token 所會儲存在鏈上的資料

Gas 優化

上述的詞彙 Metadata 在經過優化後,降低了百分之三十的 Gas Fee。我們調整了資料儲存的順序與容量,讓所有資料能以四個 256 bytes 的儲存空間被紀錄在鏈上,同時也調整了合約內的判斷邏輯,讓每位鑄造者盡可能只需要經過最少的判斷式以節省 Gas 用量。

MintverseWordV1.sol: mintPublicWord 281,004 Gas (0.014 ETH, 50 Gwei), defineWord 381,465 Gas (0.019 ETH, 50 Gwei)
MintverseWordV1.sol: mintPublicWord 281,004 Gas (0.014 ETH, 50 Gwei), defineWord 381,465 Gas (0.019 ETH, 50 Gwei)
MintverseWordV2.sol: mintPublicWord 144,951 Gas (0.007 ETH, 50 Gwei), defineWord 332,609 Gas (0.016 ETH, 50 Gwei)
MintverseWordV2.sol: mintPublicWord 144,951 Gas (0.007 ETH, 50 Gwei), defineWord 332,609 Gas (0.016 ETH, 50 Gwei)

隨機性詞彙

要做到 100% 鏈上的隨機性,需要透過 Chainlink VRF 的服務,但這樣會需要更多的 Gas,因此我們參考 Hashmasks 的作法透過 block.timestamp 與 msg.sender 來產生 hash 進而決定出 token 與詞彙庫配對的起始點,在可預測性隨機與 Gas Fee 之間取得一個平衡。

_setHeadWordId: 透過 block.timestamp & 鑄造者地址創造隨機性
_setHeadWordId: 透過 block.timestamp & 鑄造者地址創造隨機性

https://www.thehashmasks.com/

解盲時間設定

由於每個詞彙將在 5/9 進行解盲,因此開始倒數計時的時間也將不同,在合約中依據每個詞彙鑄造的時間,設定不同的倒數計時起始時間,如果是在解盲前鑄造將由解盲時間開始倒數計時,如果是在解盲後鑄造將依據鑄造時間開始倒數計時。

_getCurWordTimestamp: 判斷詞彙倒數起始時間
_getCurWordTimestamp: 判斷詞彙倒數起始時間

詞彙循環重置

白名單與公售將會配對到隨機詞彙庫中的 1900 個詞彙,而每個詞彙在 42 小時後若無人定義,將死亡並重新回到詞彙庫中,因此合約中設計了清算的機制,由官方執行 settleExpiredWord 的函式,並由 startTokenId 依序往後清算至 endTokenId,若遇到死亡詞彙則觸發事件將詞彙移至詞彙庫末端。

function settleExpiredWord(uint256 startTokenId, uint256 endTokenId)
function settleExpiredWord(uint256 startTokenId, uint256 endTokenId)

資料儲存與讀取

每個鑄造者可以透過 defineWord 函式來定義詞彙,送出交易並將資料寫入鏈上,而前端網頁以及生成式藝術引擎將會透過 getTokenProperties 函式讀取 token 的相關資料進行渲染與影像生成。以下為系統結構圖與相關的函式:

post image
function defineWord(uint256 tokenId, string calldata definer, uint8 partOfSpeech1, uint8 partOfSpeech2, string calldata relatedWord, string calldata description)
function defineWord(uint256 tokenId, string calldata definer, uint8 partOfSpeech1, uint8 partOfSpeech2, string calldata relatedWord, string calldata description)
function getTokenProperties(uint256 tokenId)public view override returns (string memory definer, uint256 wordId, uint256 categoryId, uint256 partOfSpeechId1, uint256 partOfSpeechId2, string memory relatedWord, string memory description)
function getTokenProperties(uint256 tokenId)public view override returns (string memory definer, uint256 wordId, uint256 categoryId, uint256 partOfSpeechId1, uint256 partOfSpeechId2, string memory relatedWord, string memory description)

MintverseDictionary.sol

MintverseDictionary Token 合約的主要功能則為判斷鑄造者地址是否有加購辭典,若有加購且尚未空投過則符合空投條件,會由官方承擔 Gas Fee 空投給持有者,另外也在白名單與公售的機制中與 MintverseWord Token 互動,檢查加購數量,確保總數維持在 210 個。

function airdropDictionary(address to)
function airdropDictionary(address to)

風險披露聲明 - Risk Disclosure

創新總是伴隨著風險,MintverseWord 的合約中加入了隨機性、死亡時間檢查等許多有趣的新機制及玩法,儘管我們做了許多不同情境的測試,合約仍然存在著發生錯誤的可能性,因此我們保留了緊急狀況的安全機制,確保即便錯誤發生,仍有修正與補救的機會。

但能夠修正與補救即存在中心化的成份,因此我們向所有鑄造者揭露這些中心化的地方。在以下這些函式中官方有權限對 Token 的特定資料進行修改,一共分為 SYSTEM EMERGENCY CALLSTOKEN EMERGENCY CALLS 兩部分,在系統緊急措施中,官方得以修改與配對詞彙、數量上限相關的參數,目的是為了在詞彙配對發生錯誤時,可以修正並讓計算方式回歸正常,在 Token 資料緊急措施中,官方得以修改 Token 的配對詞彙、是否經過鑄造、倒數起始時間,目的是為了在詞彙資料發生錯誤時,可以修正並讓鑄造者重新定義詞彙,但同時我們也無權控制鑄造者們所定義的內容,僅有權更改系統所配對到的資訊。

與緊急修改相關的函式一覽
與緊急修改相關的函式一覽

未來優化方向 - Future Work

這次的合約在 4/23 完成最後定案,過程中經過了許多機制的變化與迭代,其中還有許多優化與進步的空間,原先設定每個地址僅能鑄造一個因此使用 struct 紀錄每個 token 的資料,但當一個地址能夠鑄造多個時,這樣的實作則無法發揮 ERC721A Batch Mint 全部的優勢,在下一版的實作中會將 token 的 mintTime timestamp 與 wordId 改為 mapping 的格式紀錄每個地址的起始 tokenId,同時紀錄起始 token 所對應的 mintTime timestamp 與 wordId,則可以批量紀錄所有資料,另外與 token 有關的函式如:mintGiveawayDictionary, mintWhitelistWord, mintPublicWord, defineWord 也皆可以調整為批量處理的形式,方便團隊與使用者使用,而最後則希望學習 Uniswap V3: Positions NFT 將全部的生成過程做到 100% 上鏈!創作者與開發者們 Let’s Keep BUIDLing!


合約地址 & - Contract Address

去中心化資料庫 - Arweave Mapping Database URI

  • 法律條款 URI:

  • Animation Code (Word Token) URI:

  • Animation Code (Dictionary Token) URI:

  • 視覺重現方式 URI:

  • 10 篇創世小說 URI:

  • 鑄造機制 URI:

  • 詞彙ID Mapping URI:

  • 詞性ID Mapping URI:

  • 詞彙類別ID Mapping URI:

  • 詞彙 Metadata Mapping URI:

  • 辭典 Metadata Mapping URI: