Web3Rover 第一週的作業已經截止,共收到 35 份作業,占 learner 中的約 40%,算是較好的初步實現了中門檻,低人數,高參與的目標。
本期作業一共兩題 + 附加題一題,共 10+10+5=25 分。25 分和 20 分的回答皆為 11.4%,沒有 0 分。
下面是參考答案:
1,指出入學考試考試使用的 obolus 合約的一個多餘的變數。#
A:mintRate。這裡其實是我的一個失誤,本來是想設定一個價格,防止有人在測試網上大量 mint,但後來想到測試網拿水不用成本,定低了沒意義,定高了(超過一次能拿的水)又影響真正的學習者進來,於是最終取消了定價但忘記刪除了這個變數。
這題有一些同學回答是 ObolusSliver 的 ID,不知道是為何。這個變數雖然可以不用定義,但直接在程式碼裡使用屬於使用 magic number,並不推薦。
2,指出 obolus 合約是如何做到一個錢包只能擁有一個的。#
A:這一題準確來說有三處,所以其實真正答完的只有一位(但第二處沒答我也算對了)。
第一處:require(balanceOf(msg.sender, ObolusSliver) == 0, "You already have one Obolus.");
這裡是確保 mint 前錢包中的 ObolusSliver 數為 0。
此處重點是 ERC1155 的balanceOf(address, tokenId)
,這裡就是上面所說的,你可以直接使用 0,但因為是魔數,並不推薦。
第二處:require(amount == 1, "Wrong amount. Should be 1");
這條保證了每次 mint 必須只能 mint 一個。
第三處:require(address(0) == from, "You can not give your Obolus to others.");
這條是回答中最容易被忽略掉的一條,在 _beforeTokenTransfer
中。大家仔細想一下就知道,如果僅憑上面兩條,是沒法防住 “mint 之後將 token 轉入其他已經有 token 的錢包達到持有數大於 1” 這種情況。
所以這行程式碼直接限制了除了 0 地址之外,沒有任何人能將該 token 轉移。至於為什麼要限制為 0 地址其實也是一個很好的思考題 -- 有沒有想過,這個 NFT 的 mint,是從哪個地址 mint 出來的?
3,(附加題)指出為什麼 ERC1155 不適合用於有著不同 trait 的 pfp 項目。#
這題其實能說很多很多,但核心就在於 ERC1155 是通過雙層 mapping 來實現一個合約可以存儲多種 token 的,這裡的 token 不僅僅指 NFT,也同樣指 FT。
ERC1155 的 tokenID 和 ERC721 的 tokenID 最大不同在於,在 1155 中,一個 tokenID 代表著一種token。而在 721 中,因為總共只有一種 token,所以 tokenID 代表的是每個token 的編號。
這次考試使用的是 1155,大家可以看到 tokenID 只有一個,ObolusSliver (也就是 0),即代表著這個 erc1155 只包含了一種token。而深入到 ObolusSliver 這個 token 裡面,每一個 token 本身是沒有自己的編號的,也就是和別人的並無不同。這種設計其實是為了兼容 FT,在默認的 erc1155 接口下,ft 和 nft 可以表現出一樣的行為。
總而言之,erc1155 規定了多種token,tokenID 是用來標記不同種類的 token 的,每種 token 即使是 NFT 自己內部是和 FT 一樣沒有編號上的差別的。而 ERC721 只能包含一種 token,tokenID 是用來標記每個token 的編號。
說到底,721 的 trait 系統是完全依賴於 tokenID 來分配 metadata 的,這種設計上的不同也導致了,在 erc1155 中由於同一種 token 沒有編號上的區別,默認情況下是沒有辦法為同一種裡每一個 token 分配不同的 metadata 的。
當然這一切並不絕對,事實上開發者完全可以自己添加邏輯來記錄 1155 下每一種 token 裡的每一個的 id,只不過需要更多的工作和更多的 gas 消耗。
我們的官方推特: