From eb8db9c7f136bdc92c9168b2359014607d8aea8e Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 31 Dec 2024 15:18:03 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20hydai/so?= =?UTF-8?q?lidity.tw@5330c430269edb382368dc40ffce2b111ca339f3=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 404.html | 6 +++--- assets/js/{24.25b53c7a.js => 24.2f9c6cc2.js} | 2 +- assets/js/{25.9abed7ff.js => 25.1ecda9e0.js} | 2 +- assets/js/{26.3057b08a.js => 26.e699b744.js} | 2 +- assets/js/{27.eb393f01.js => 27.1749641b.js} | 2 +- assets/js/{29.5e017797.js => 29.2e878408.js} | 2 +- assets/js/{35.ec1d48ed.js => 35.8e5a422e.js} | 2 +- assets/js/{36.7ad1a99a.js => 36.c3b1843c.js} | 2 +- assets/js/{37.29d69bba.js => 37.48d45ab3.js} | 2 +- assets/js/{38.74807ea4.js => 38.7b042d65.js} | 2 +- assets/js/{46.67cc6973.js => 46.a01f013b.js} | 2 +- assets/js/{47.d878efb0.js => 47.2941f6f7.js} | 2 +- assets/js/{50.43fa6b01.js => 50.b054b2ac.js} | 2 +- assets/js/{51.e45a8c2a.js => 51.a77781e8.js} | 2 +- assets/js/{52.0e25339e.js => 52.49f60f8e.js} | 2 +- assets/js/{53.1aba8f81.js => 53.bfec46ab.js} | 2 +- assets/js/{54.565c39aa.js => 54.b525daad.js} | 2 +- assets/js/{app.436a37a8.js => app.ae23d1a4.js} | 4 ++-- ...74\346\230\257\345\215\200\345\241\212\351\217\210.html" | 6 +++--- ...12\344\273\200\351\272\274\346\230\257\351\217\210.html" | 6 +++--- ...00\351\272\274\346\230\257\344\272\244\346\230\223.html" | 6 +++--- ...31\350\210\207\346\211\213\347\272\214\350\262\273.html" | 6 +++--- "ethereum-101/05-\345\270\263\346\210\266.html" | 6 +++--- "ethereum-101/06-\347\266\262\350\267\257.html" | 6 +++--- ...7-\345\205\261\350\255\230\346\251\237\345\210\266.html" | 6 +++--- ...45\344\275\234\351\207\217\350\255\211\346\230\216.html" | 6 +++--- ...9-\346\254\212\347\233\212\350\255\211\346\230\216.html" | 6 +++--- ...04\344\270\215\345\220\214\345\261\244\347\264\232.html" | 6 +++--- ...12\346\224\271\350\211\257\346\217\220\346\241\210.html" | 6 +++--- ...13\346\261\202\346\204\217\350\246\213\347\250\277.html" | 6 +++--- ...20\344\273\243\345\271\243\346\250\231\346\272\226.html" | 6 +++--- "ethereum-101/14-ERC20\344\276\213\345\255\220.html" | 6 +++--- ...357\274\210NFT\357\274\211\346\250\231\346\272\226.html" | 6 +++--- ...23\264\345\205\205\357\274\210metadata\357\274\211.html" | 6 +++--- ...04\345\210\227\350\210\211\346\223\264\345\205\205.html" | 6 +++--- .../18-ERC721A\347\232\204\346\224\271\351\200\262.html" | 6 +++--- ...351\221\221\350\263\236\346\234\237\347\232\204NFT.html" | 6 +++--- ...03\344\273\243\345\271\243\346\250\231\346\272\226.html" | 6 +++--- .../21-ERC1155\347\232\204\346\241\210\344\276\213.html" | 6 +++--- ...AP\345\217\203\350\210\207\350\255\211\346\230\216.html" | 6 +++--- ...\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" | 6 +++--- ...\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" | 6 +++--- ...\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" | 6 +++--- ...\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" | 6 +++--- ...\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" | 6 +++--- ...\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" | 6 +++--- ...\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" | 6 +++--- "ethereum-101/30-\347\265\220\350\252\236.html" | 6 +++--- ethereum-101/index.html | 6 +++--- head-first-eof-lecture-notes/index.html | 6 +++--- "head-first-eof/01-\345\211\215\350\250\200.html" | 6 +++--- head-first-eof/index.html | 6 +++--- index.html | 6 +++--- 53 files changed, 126 insertions(+), 126 deletions(-) rename assets/js/{24.25b53c7a.js => 24.2f9c6cc2.js} (98%) rename assets/js/{25.9abed7ff.js => 25.1ecda9e0.js} (98%) rename assets/js/{26.3057b08a.js => 26.e699b744.js} (99%) rename assets/js/{27.eb393f01.js => 27.1749641b.js} (98%) rename assets/js/{29.5e017797.js => 29.2e878408.js} (97%) rename assets/js/{35.ec1d48ed.js => 35.8e5a422e.js} (99%) rename assets/js/{36.7ad1a99a.js => 36.c3b1843c.js} (97%) rename assets/js/{37.29d69bba.js => 37.48d45ab3.js} (98%) rename assets/js/{38.74807ea4.js => 38.7b042d65.js} (99%) rename assets/js/{46.67cc6973.js => 46.a01f013b.js} (99%) rename assets/js/{47.d878efb0.js => 47.2941f6f7.js} (99%) rename assets/js/{50.43fa6b01.js => 50.b054b2ac.js} (99%) rename assets/js/{51.e45a8c2a.js => 51.a77781e8.js} (99%) rename assets/js/{52.0e25339e.js => 52.49f60f8e.js} (98%) rename assets/js/{53.1aba8f81.js => 53.bfec46ab.js} (89%) rename assets/js/{54.565c39aa.js => 54.b525daad.js} (99%) rename assets/js/{app.436a37a8.js => app.ae23d1a4.js} (82%) diff --git a/404.html b/404.html index 1ed8f76..829ad15 100644 --- a/404.html +++ b/404.html @@ -8,13 +8,13 @@ - + -

404

There's nothing here.
+ - + diff --git a/assets/js/24.25b53c7a.js b/assets/js/24.2f9c6cc2.js similarity index 98% rename from assets/js/24.25b53c7a.js rename to assets/js/24.2f9c6cc2.js index 0621f7d..d59693f 100644 --- a/assets/js/24.25b53c7a.js +++ b/assets/js/24.2f9c6cc2.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{346:function(t,v,_){"use strict";_.r(v);var a=_(17),e=Object(a.a)({},(function(){var t=this,v=t._self._c;return v("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[v("h1",{attrs:{id:"何謂區塊-何謂鏈"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#何謂區塊-何謂鏈"}},[t._v("#")]),t._v(" 何謂區塊?何謂鏈?")]),t._v(" "),v("p",[t._v("在上一篇文章中,我們用了「麻將」的概念來講一個以太坊的粗淺比喻,希望能幫助大家有個大略的想像。接下來,將以名詞解釋系列,一步步補充這些背景知識。")]),t._v(" "),v("h2",{attrs:{id:"區塊"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#區塊"}},[t._v("#")]),t._v(" 區塊")]),t._v(" "),v("p",[t._v("區塊鏈,顧名思義,是由「區塊(Block)」與「鏈(Chain)」所組成的名詞。要理解區塊鏈,我們就要先理解這兩個名詞實際上的含義。")]),t._v(" "),v("p",[t._v("天地洪荒,萬物混沌之初,這世界本沒區塊,直到「創始區塊(Genesis Block)」的出現,才定義了萬物的狀態。有了基礎的狀態,在未來的每個區塊只需要記錄「狀態的變化」即可。")]),t._v(" "),v("p",[t._v("因此,在一個區塊裡面包含了多筆「交易(Transaction)」,而在以太坊裡的交易又分為:「建立(Create)」與「執行(Execute)」。")]),t._v(" "),v("h3",{attrs:{id:"建立-create"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#建立-create"}},[t._v("#")]),t._v(" 建立(Create)")]),t._v(" "),v("p",[t._v("通常發生在「部署智能合約」所使用。我們將在智能合約章節有詳細的解釋。")]),t._v(" "),v("h3",{attrs:{id:"執行-execute"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#執行-execute"}},[t._v("#")]),t._v(" 執行(Execute)")]),t._v(" "),v("p",[t._v("代表著以下幾種可能的狀態變化:")]),t._v(" "),v("ol",[v("li",[t._v("收發以太(Ether):增減該帳戶的 Ether 餘額。")]),t._v(" "),v("li",[t._v("與智能合約互動:改變智能合約的儲存資料。")])]),t._v(" "),v("h4",{attrs:{id:"以創始區塊為例"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#以創始區塊為例"}},[t._v("#")]),t._v(" 以創始區塊為例")]),t._v(" "),v("p",[t._v("圖片擷取自:https://etherscan.io/txs?block=0\n"),v("img",{attrs:{src:"https://i.imgur.com/YeqBlMJ.png",alt:""}})]),t._v(" "),v("p",[t._v("我們可以發現這個創始區塊紀錄了多筆由「GENESIS」轉給「以太坊帳戶」的以太轉帳。")]),t._v(" "),v("h4",{attrs:{id:"以第15553296區塊為例"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#以第15553296區塊為例"}},[t._v("#")]),t._v(" 以第15553296區塊為例")]),t._v(" "),v("p",[t._v("圖片擷取自:https://etherscan.io/txs?block=15553296\n"),v("img",{attrs:{src:"https://i.imgur.com/nerGTfY.png",alt:""}})]),t._v(" "),v("p",[t._v("在這個區塊中,就能看到很多與智能合約互動的交易,比如說近期熱門的 NFT 就會提供一個 "),v("code",[t._v("Mint")]),t._v(" 的函式,讓使用者可以鑄造 NFT 出來。")]),t._v(" "),v("h2",{attrs:{id:"鏈"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#鏈"}},[t._v("#")]),t._v(" 鏈")]),t._v(" "),v("p",[t._v("有了對區塊的初步概念,我們就能來探討「鏈」了。")]),t._v(" "),v("p",[t._v("鏈的目的是把區塊有順序地給串起來。而為什麼「順序」如此重要呢?")]),t._v(" "),v("p",[t._v("每個區塊實際上是記錄「交易」,也就是「狀態的變化」,如果順序不同會發生什麼事?")]),t._v(" "),v("h3",{attrs:{id:"以銀行交易為例"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#以銀行交易為例"}},[t._v("#")]),t._v(" 以銀行交易為例")]),t._v(" "),v("p",[t._v("Alice 的戶頭有 100 元,Bob 的戶頭有 200 元,海帶的戶頭有 300 元")]),t._v(" "),v("p",[v("strong",[t._v("初始狀態")])]),t._v(" "),v("table",[v("thead",[v("tr",[v("th",[t._v("Alice")]),t._v(" "),v("th",[t._v("Bob")]),t._v(" "),v("th",[t._v("海帶")])])]),t._v(" "),v("tbody",[v("tr",[v("td",[t._v("100")]),t._v(" "),v("td",[t._v("200")]),t._v(" "),v("td",[t._v("300")])])])]),t._v(" "),v("p",[t._v("Alice 今天請海帶幫忙代購商品,欠了海帶 200 元。\n而 Bob 同時欠了 Alice 100 元。\nAlice 為了能還海帶錢,請 Bob 先還她 100 元。")]),t._v(" "),v("p",[v("strong",[t._v("Bob 還錢後的狀態")])]),t._v(" "),v("table",[v("thead",[v("tr",[v("th",[t._v("Alice")]),t._v(" "),v("th",[t._v("Bob")]),t._v(" "),v("th",[t._v("海帶")])])]),t._v(" "),v("tbody",[v("tr",[v("td",[t._v("200")]),t._v(" "),v("td",[t._v("100")]),t._v(" "),v("td",[t._v("300")])])])]),t._v(" "),v("p",[t._v("Alice 這時還給海帶 200 元")]),t._v(" "),v("p",[v("strong",[t._v("最終狀態")])]),t._v(" "),v("table",[v("thead",[v("tr",[v("th",[t._v("Alice")]),t._v(" "),v("th",[t._v("Bob")]),t._v(" "),v("th",[t._v("海帶")])])]),t._v(" "),v("tbody",[v("tr",[v("td",[t._v("0")]),t._v(" "),v("td",[t._v("100")]),t._v(" "),v("td",[t._v("500")])])])]),t._v(" "),v("p",[t._v("上面的交易如果順序亂了, Alice 要還錢的交易被放在 Bob 還錢之前,那發生的瞬間就會因為餘額不足導致交易失敗。")]),t._v(" "),v("h2",{attrs:{id:"結語"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#結語"}},[t._v("#")]),t._v(" 結語")]),t._v(" "),v("p",[t._v("同理在區塊鏈上前面交易的順序、成功與否都會影響後面的狀態,因此我們需要通過「鏈」的概念確保所有的「區塊」都能以一個不可變動的順序被牢牢的串在一起。")]),t._v(" "),v("p",[t._v("而這,就是區塊鏈。")])])}),[],!1,null,null,null);v.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{345:function(t,v,_){"use strict";_.r(v);var a=_(17),e=Object(a.a)({},(function(){var t=this,v=t._self._c;return v("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[v("h1",{attrs:{id:"何謂區塊-何謂鏈"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#何謂區塊-何謂鏈"}},[t._v("#")]),t._v(" 何謂區塊?何謂鏈?")]),t._v(" "),v("p",[t._v("在上一篇文章中,我們用了「麻將」的概念來講一個以太坊的粗淺比喻,希望能幫助大家有個大略的想像。接下來,將以名詞解釋系列,一步步補充這些背景知識。")]),t._v(" "),v("h2",{attrs:{id:"區塊"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#區塊"}},[t._v("#")]),t._v(" 區塊")]),t._v(" "),v("p",[t._v("區塊鏈,顧名思義,是由「區塊(Block)」與「鏈(Chain)」所組成的名詞。要理解區塊鏈,我們就要先理解這兩個名詞實際上的含義。")]),t._v(" "),v("p",[t._v("天地洪荒,萬物混沌之初,這世界本沒區塊,直到「創始區塊(Genesis Block)」的出現,才定義了萬物的狀態。有了基礎的狀態,在未來的每個區塊只需要記錄「狀態的變化」即可。")]),t._v(" "),v("p",[t._v("因此,在一個區塊裡面包含了多筆「交易(Transaction)」,而在以太坊裡的交易又分為:「建立(Create)」與「執行(Execute)」。")]),t._v(" "),v("h3",{attrs:{id:"建立-create"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#建立-create"}},[t._v("#")]),t._v(" 建立(Create)")]),t._v(" "),v("p",[t._v("通常發生在「部署智能合約」所使用。我們將在智能合約章節有詳細的解釋。")]),t._v(" "),v("h3",{attrs:{id:"執行-execute"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#執行-execute"}},[t._v("#")]),t._v(" 執行(Execute)")]),t._v(" "),v("p",[t._v("代表著以下幾種可能的狀態變化:")]),t._v(" "),v("ol",[v("li",[t._v("收發以太(Ether):增減該帳戶的 Ether 餘額。")]),t._v(" "),v("li",[t._v("與智能合約互動:改變智能合約的儲存資料。")])]),t._v(" "),v("h4",{attrs:{id:"以創始區塊為例"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#以創始區塊為例"}},[t._v("#")]),t._v(" 以創始區塊為例")]),t._v(" "),v("p",[t._v("圖片擷取自:https://etherscan.io/txs?block=0\n"),v("img",{attrs:{src:"https://i.imgur.com/YeqBlMJ.png",alt:""}})]),t._v(" "),v("p",[t._v("我們可以發現這個創始區塊紀錄了多筆由「GENESIS」轉給「以太坊帳戶」的以太轉帳。")]),t._v(" "),v("h4",{attrs:{id:"以第15553296區塊為例"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#以第15553296區塊為例"}},[t._v("#")]),t._v(" 以第15553296區塊為例")]),t._v(" "),v("p",[t._v("圖片擷取自:https://etherscan.io/txs?block=15553296\n"),v("img",{attrs:{src:"https://i.imgur.com/nerGTfY.png",alt:""}})]),t._v(" "),v("p",[t._v("在這個區塊中,就能看到很多與智能合約互動的交易,比如說近期熱門的 NFT 就會提供一個 "),v("code",[t._v("Mint")]),t._v(" 的函式,讓使用者可以鑄造 NFT 出來。")]),t._v(" "),v("h2",{attrs:{id:"鏈"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#鏈"}},[t._v("#")]),t._v(" 鏈")]),t._v(" "),v("p",[t._v("有了對區塊的初步概念,我們就能來探討「鏈」了。")]),t._v(" "),v("p",[t._v("鏈的目的是把區塊有順序地給串起來。而為什麼「順序」如此重要呢?")]),t._v(" "),v("p",[t._v("每個區塊實際上是記錄「交易」,也就是「狀態的變化」,如果順序不同會發生什麼事?")]),t._v(" "),v("h3",{attrs:{id:"以銀行交易為例"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#以銀行交易為例"}},[t._v("#")]),t._v(" 以銀行交易為例")]),t._v(" "),v("p",[t._v("Alice 的戶頭有 100 元,Bob 的戶頭有 200 元,海帶的戶頭有 300 元")]),t._v(" "),v("p",[v("strong",[t._v("初始狀態")])]),t._v(" "),v("table",[v("thead",[v("tr",[v("th",[t._v("Alice")]),t._v(" "),v("th",[t._v("Bob")]),t._v(" "),v("th",[t._v("海帶")])])]),t._v(" "),v("tbody",[v("tr",[v("td",[t._v("100")]),t._v(" "),v("td",[t._v("200")]),t._v(" "),v("td",[t._v("300")])])])]),t._v(" "),v("p",[t._v("Alice 今天請海帶幫忙代購商品,欠了海帶 200 元。\n而 Bob 同時欠了 Alice 100 元。\nAlice 為了能還海帶錢,請 Bob 先還她 100 元。")]),t._v(" "),v("p",[v("strong",[t._v("Bob 還錢後的狀態")])]),t._v(" "),v("table",[v("thead",[v("tr",[v("th",[t._v("Alice")]),t._v(" "),v("th",[t._v("Bob")]),t._v(" "),v("th",[t._v("海帶")])])]),t._v(" "),v("tbody",[v("tr",[v("td",[t._v("200")]),t._v(" "),v("td",[t._v("100")]),t._v(" "),v("td",[t._v("300")])])])]),t._v(" "),v("p",[t._v("Alice 這時還給海帶 200 元")]),t._v(" "),v("p",[v("strong",[t._v("最終狀態")])]),t._v(" "),v("table",[v("thead",[v("tr",[v("th",[t._v("Alice")]),t._v(" "),v("th",[t._v("Bob")]),t._v(" "),v("th",[t._v("海帶")])])]),t._v(" "),v("tbody",[v("tr",[v("td",[t._v("0")]),t._v(" "),v("td",[t._v("100")]),t._v(" "),v("td",[t._v("500")])])])]),t._v(" "),v("p",[t._v("上面的交易如果順序亂了, Alice 要還錢的交易被放在 Bob 還錢之前,那發生的瞬間就會因為餘額不足導致交易失敗。")]),t._v(" "),v("h2",{attrs:{id:"結語"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#結語"}},[t._v("#")]),t._v(" 結語")]),t._v(" "),v("p",[t._v("同理在區塊鏈上前面交易的順序、成功與否都會影響後面的狀態,因此我們需要通過「鏈」的概念確保所有的「區塊」都能以一個不可變動的順序被牢牢的串在一起。")]),t._v(" "),v("p",[t._v("而這,就是區塊鏈。")])])}),[],!1,null,null,null);v.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/25.9abed7ff.js b/assets/js/25.1ecda9e0.js similarity index 98% rename from assets/js/25.9abed7ff.js rename to assets/js/25.1ecda9e0.js index 03be711..ba0e5bd 100644 --- a/assets/js/25.9abed7ff.js +++ b/assets/js/25.1ecda9e0.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{347:function(a,t,v){"use strict";v.r(t);var _=v(17),e=Object(_.a)({},(function(){var a=this,t=a._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[t("h1",{attrs:{id:"什麼是交易-transaction"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#什麼是交易-transaction"}},[a._v("#")]),a._v(" 什麼是交易(Transaction)")]),a._v(" "),t("p",[a._v("在昨天的區塊鏈名詞解釋中,我們粗略地提到了「交易」,那麼今天,就來好好聊聊交易裡有什麼資訊吧!")]),a._v(" "),t("h2",{attrs:{id:"交易的定義"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#交易的定義"}},[a._v("#")]),a._v(" 交易的定義")]),a._v(" "),t("p",[a._v("交易(Transaction)指的是由一個帳號(Account)發起的一種「改變狀態」的行為。\n比如說,Alice 轉帳一顆 Ether 給 Bob。這筆交易就會把 Alice 的帳戶扣掉一顆 Ether,且幫 Bob 的帳戶加上一顆 Ether。")]),a._v(" "),t("h2",{attrs:{id:"交易的欄位"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#交易的欄位"}},[a._v("#")]),a._v(" 交易的欄位")]),a._v(" "),t("p",[a._v("一個合法的交易會包含以下幾個欄位:")]),a._v(" "),t("ul",[t("li",[a._v("接收者(recipient)\n"),t("ul",[t("li",[a._v("接收的位址(Address),如果接收的位址是一個 EOA ,則這筆交易將會轉移 Value(請參考 Value 欄位);若接收的位址是個合約,則這筆交易將會使用 "),t("code",[a._v("data")]),a._v(" 欄位作為輸入資料,來執行合約裡的程式碼。")])])]),a._v(" "),t("li",[a._v("簽名(signature)\n"),t("ul",[t("li",[a._v("發送者的識別碼。這個簽名是由發送者的私鑰(Private Key)所簽署,用來確保這筆交易是通過發送者的授權。")])])]),a._v(" "),t("li",[a._v("nonce(不確定中文翻譯,根據國家教育研究院應使用「臨時用法」這個專有名詞)\n"),t("ul",[t("li",[a._v("一個有序且遞增的計數器,用來記錄該帳戶(Account)的交易數量。")])])]),a._v(" "),t("li",[a._v("以太的數量(value)\n"),t("ul",[t("li",[a._v("從發送者轉移至接收者的 ETH 數量。")]),a._v(" "),t("li",[a._v("單位為 WEI,為 Ethereum 的最小面值單位。")])])]),a._v(" "),t("li",[a._v("資料(data)\n"),t("ul",[t("li",[a._v("非必需欄位,用來儲存任意的資料。")])])]),a._v(" "),t("li",[a._v("燃料單位上限(gasLimit)\n"),t("ul",[t("li",[a._v("能被此交易消耗的燃料單位上限。")]),a._v(" "),t("li",[a._v("實際付出的手續費為(每單位燃料的費用上限)*(燃料單位上限)")]),a._v(" "),t("li",[a._v("燃料的概念我們之後的章節會提到。")])])]),a._v(" "),t("li",[a._v("每單位燃料的優先價格上限(maxPriorityFeePerGas)\n"),t("ul",[t("li",[a._v("給礦工或驗證者的小費。")]),a._v(" "),t("li",[a._v("小費數量的上限。")]),a._v(" "),t("li",[a._v("想要讓自己的交易更優先被處理,這邊可以多塞點錢。")])])]),a._v(" "),t("li",[a._v("每單位燃料的價格上限(maxFeePerGas)\n"),t("ul",[t("li",[a._v("允許此交易的最大燃料價格上限,包含基礎燃料單位費用(baseFeePerGas)與優先燃料單位費用(maxPriorityFeePerGas)")])])])]),a._v(" "),t("h2",{attrs:{id:"結語"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#結語"}},[a._v("#")]),a._v(" 結語")]),a._v(" "),t("p",[a._v("今天就先解釋到這邊,明天再讓我們來聊聊燃料(Gas)的概念。")])])}),[],!1,null,null,null);t.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{346:function(a,t,v){"use strict";v.r(t);var _=v(17),e=Object(_.a)({},(function(){var a=this,t=a._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[t("h1",{attrs:{id:"什麼是交易-transaction"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#什麼是交易-transaction"}},[a._v("#")]),a._v(" 什麼是交易(Transaction)")]),a._v(" "),t("p",[a._v("在昨天的區塊鏈名詞解釋中,我們粗略地提到了「交易」,那麼今天,就來好好聊聊交易裡有什麼資訊吧!")]),a._v(" "),t("h2",{attrs:{id:"交易的定義"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#交易的定義"}},[a._v("#")]),a._v(" 交易的定義")]),a._v(" "),t("p",[a._v("交易(Transaction)指的是由一個帳號(Account)發起的一種「改變狀態」的行為。\n比如說,Alice 轉帳一顆 Ether 給 Bob。這筆交易就會把 Alice 的帳戶扣掉一顆 Ether,且幫 Bob 的帳戶加上一顆 Ether。")]),a._v(" "),t("h2",{attrs:{id:"交易的欄位"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#交易的欄位"}},[a._v("#")]),a._v(" 交易的欄位")]),a._v(" "),t("p",[a._v("一個合法的交易會包含以下幾個欄位:")]),a._v(" "),t("ul",[t("li",[a._v("接收者(recipient)\n"),t("ul",[t("li",[a._v("接收的位址(Address),如果接收的位址是一個 EOA ,則這筆交易將會轉移 Value(請參考 Value 欄位);若接收的位址是個合約,則這筆交易將會使用 "),t("code",[a._v("data")]),a._v(" 欄位作為輸入資料,來執行合約裡的程式碼。")])])]),a._v(" "),t("li",[a._v("簽名(signature)\n"),t("ul",[t("li",[a._v("發送者的識別碼。這個簽名是由發送者的私鑰(Private Key)所簽署,用來確保這筆交易是通過發送者的授權。")])])]),a._v(" "),t("li",[a._v("nonce(不確定中文翻譯,根據國家教育研究院應使用「臨時用法」這個專有名詞)\n"),t("ul",[t("li",[a._v("一個有序且遞增的計數器,用來記錄該帳戶(Account)的交易數量。")])])]),a._v(" "),t("li",[a._v("以太的數量(value)\n"),t("ul",[t("li",[a._v("從發送者轉移至接收者的 ETH 數量。")]),a._v(" "),t("li",[a._v("單位為 WEI,為 Ethereum 的最小面值單位。")])])]),a._v(" "),t("li",[a._v("資料(data)\n"),t("ul",[t("li",[a._v("非必需欄位,用來儲存任意的資料。")])])]),a._v(" "),t("li",[a._v("燃料單位上限(gasLimit)\n"),t("ul",[t("li",[a._v("能被此交易消耗的燃料單位上限。")]),a._v(" "),t("li",[a._v("實際付出的手續費為(每單位燃料的費用上限)*(燃料單位上限)")]),a._v(" "),t("li",[a._v("燃料的概念我們之後的章節會提到。")])])]),a._v(" "),t("li",[a._v("每單位燃料的優先價格上限(maxPriorityFeePerGas)\n"),t("ul",[t("li",[a._v("給礦工或驗證者的小費。")]),a._v(" "),t("li",[a._v("小費數量的上限。")]),a._v(" "),t("li",[a._v("想要讓自己的交易更優先被處理,這邊可以多塞點錢。")])])]),a._v(" "),t("li",[a._v("每單位燃料的價格上限(maxFeePerGas)\n"),t("ul",[t("li",[a._v("允許此交易的最大燃料價格上限,包含基礎燃料單位費用(baseFeePerGas)與優先燃料單位費用(maxPriorityFeePerGas)")])])])]),a._v(" "),t("h2",{attrs:{id:"結語"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#結語"}},[a._v("#")]),a._v(" 結語")]),a._v(" "),t("p",[a._v("今天就先解釋到這邊,明天再讓我們來聊聊燃料(Gas)的概念。")])])}),[],!1,null,null,null);t.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/26.3057b08a.js b/assets/js/26.e699b744.js similarity index 99% rename from assets/js/26.3057b08a.js rename to assets/js/26.e699b744.js index c63fa02..abb0a44 100644 --- a/assets/js/26.3057b08a.js +++ b/assets/js/26.e699b744.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[26],{345:function(a,e,t){"use strict";t.r(e);var v=t(17),_=Object(v.a)({},(function(){var a=this,e=a._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h1",{attrs:{id:"燃料-gas-與手續費-fee"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#燃料-gas-與手續費-fee"}},[a._v("#")]),a._v(" 燃料(Gas)與手續費(Fee)")]),a._v(" "),e("p",[a._v("在昨天討論交易(Transaction)的時候,想必最後的三個欄位「燃料單位上限(GasLimit)」、「每單位燃料的優先價格上限(MaxPriorityFeePerGas)」、「每單位燃料的價格上限(MaxFeePerGas)」讓大家覺得很困惑吧。")]),a._v(" "),e("p",[a._v("今天就讓我們來介紹燃料(Gas)與手續費(Fee)的機制。")]),a._v(" "),e("h2",{attrs:{id:"燃料-gas"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#燃料-gas"}},[a._v("#")]),a._v(" 燃料(Gas)")]),a._v(" "),e("p",[a._v("在以太坊(Ethereum)上的所有交易實際上都是在「執行特定的操作」,對狀態進行改變(如:帳戶餘額的轉移、部署新合約、與合約互動等)。而進行這些操作自然就會對節點與網路產生「運算資源的消耗」。")]),a._v(" "),e("p",[a._v("基於使用者付費的原則,發起交易的帳戶便需要為了這些「運算資源」來支付手續費。")]),a._v(" "),e("p",[a._v("燃料(Gas)便是一種用來表達「被消耗的運算資源」的單位。")]),a._v(" "),e("p",[a._v("或許你會有個疑問,在電腦或手機上執行軟體,不是都通過消耗的電(瓦特*小時)、或者佔用的運算資源(佔用 CPU 多少執行時間、使用多少記憶體等)來進行計費嗎?為什麼到了以太坊上變成一個奇怪的單位。\n這是因為節點並不是執行在「完全相同型號的機器上」,任何人只要滿足運行節點的最低標準需求,便可以在任何的電腦設備(包含但不限於:桌上型電腦、筆記型電腦、開發版、迷你電腦、手機等)上運行。因此幾乎不可能通過硬體規格來進行消耗運算資源的估價。")]),a._v(" "),e("p",[a._v("為了解決這個問題,以太坊設計了以太坊虛擬機(Ethereum Virtual Machine,簡稱 EVM),將所有運算資源抽象化,對每一種指令的操作都明定價碼,因此便能統一評估「被消耗的運算資源」囉!\n關於 EVM 我們會在後續的章節有更深的探討,這邊就暫時不展開了。")]),a._v(" "),e("h2",{attrs:{id:"燃料數量上限-gaslimit"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#燃料數量上限-gaslimit"}},[a._v("#")]),a._v(" 燃料數量上限(GasLimit)")]),a._v(" "),e("p",[a._v("燃料數量上限(GasLimit)是指在一筆交易中,發起者願意支付的最大燃料數量上限。")]),a._v(" "),e("p",[a._v("請特別留意,執行越多的操作將會需要燃燒更多的燃料 。因此在部署合約或者與合約互動時,通常需要將這個數字設定的高一些,以支付足夠的數量來讓交易能夠完成。")]),a._v(" "),e("p",[a._v("另外,如果只有轉移 Ether 給其他帳戶,這個操作需要 21,000 單位的燃料作為燃料數量上限。")]),a._v(" "),e("h3",{attrs:{id:"以轉帳為例"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#以轉帳為例"}},[a._v("#")]),a._v(" 以轉帳為例")]),a._v(" "),e("p",[a._v("假設 Alice 要轉給 Bob 一顆 Ether,Alice 將這筆交易的 gas limit 設定為 40,000。而一筆轉移 Ether 的操作需要燃燒 21,000 單位。在執行完轉帳以後,Alice 將會收到一筆 (40,000 - 21,000) = 19,000 單位的燃料退款。")]),a._v(" "),e("p",[a._v("反之,Alice 太過於小氣,只把 gas limit 設定成 10,000 單位,將導致燃料不夠用的情況,此時這筆交易將會失敗,並被標記成 "),e("code",[a._v("revert")]),a._v(" 的狀態,也不會有任何燃料被退回。")]),a._v(" "),e("h2",{attrs:{id:"改變計價模式的倫敦升級-london-upgrade"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#改變計價模式的倫敦升級-london-upgrade"}},[a._v("#")]),a._v(" 改變計價模式的倫敦升級(London Upgrade)")]),a._v(" "),e("p",[a._v("以太坊在倫敦升級時改變了燃料相關的計價模式,由於此處可以展開的範圍過大,讓我們下一章節再來討論,以下將以升級後的現在進行說明。")]),a._v(" "),e("h2",{attrs:{id:"基礎費用-base-fee"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#基礎費用-base-fee"}},[a._v("#")]),a._v(" 基礎費用(Base Fee)")]),a._v(" "),e("p",[a._v("每個區塊都有基礎費用,當發送者要發出交易時,設定的基礎費用不得低於該區塊的基礎費用。")]),a._v(" "),e("p",[a._v("請注意,這個基礎費用是通過一個公式進行計算的,其數值與前一個區塊所消耗掉的燃料數量有關。細節我們等倫敦升級章節再行探討。")]),a._v(" "),e("p",[a._v("當一筆交易被收入區塊中,這筆基礎費用將會直接燒毀,永遠地消失在這世界上。")]),a._v(" "),e("p",[a._v("燒到的手續費=基礎費用*使用掉的燃料數量。")]),a._v(" "),e("h2",{attrs:{id:"優先費用-priority-fee"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#優先費用-priority-fee"}},[a._v("#")]),a._v(" 優先費用(Priority Fee)")]),a._v(" "),e("p",[a._v("這是個資本主義的世界,就像去迪士尼樂園一樣,不想和其他人一起排隊,可以購買快速通行券來加速搭乘遊樂設施,通過課金來升級體驗。")]),a._v(" "),e("p",[a._v("在以太坊的世界也一樣,當每筆交易都支付一樣的單位費用時,人人平等,全部慢慢排隊,但也可以通過付點小費給礦工,讓礦工優先將交易放入區塊中,這個機制就是優先費用。")]),a._v(" "),e("p",[a._v("跟基礎費用不同的是,優先費用所產生的手續費會全部交給礦工。")]),a._v(" "),e("p",[a._v("給礦工的小費=優先費用*使用掉的燃料數量。")]),a._v(" "),e("h2",{attrs:{id:"單位燃料費用上限-max-fee"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#單位燃料費用上限-max-fee"}},[a._v("#")]),a._v(" 單位燃料費用上限(Max Fee)")]),a._v(" "),e("p",[a._v("對於使用者而言,每次發送交易都要設定基礎費用與優先費用是非常繁瑣的,為了提升體驗,因此衍生出單位燃料費用上限的概念。")]),a._v(" "),e("p",[a._v("單位燃料費用上限=基礎費用+優先費用")]),a._v(" "),e("p",[a._v("而基礎費用又是由公式與前一個區塊狀況而定,使用者無法自行決定,因此對於使用者而言,只需要設定「單位燃料上限」,發起交易的工具就會自動幫忙計算出「優先費用」了。")]),a._v(" "),e("h2",{attrs:{id:"手續費-fee"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#手續費-fee"}},[a._v("#")]),a._v(" 手續費(Fee)")]),a._v(" "),e("p",[a._v("總手續費=單位燃料費(Max Fee)*使用的燃料數量(Used Gas)。")]),a._v(" "),e("p",[a._v("當使用掉的燃數量將大於燃料數量上限時,交易將會失敗,此時的使用掉的燃料數量就會剛好等於燃料數量上限。")])])}),[],!1,null,null,null);e.default=_.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[26],{347:function(a,e,t){"use strict";t.r(e);var v=t(17),_=Object(v.a)({},(function(){var a=this,e=a._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h1",{attrs:{id:"燃料-gas-與手續費-fee"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#燃料-gas-與手續費-fee"}},[a._v("#")]),a._v(" 燃料(Gas)與手續費(Fee)")]),a._v(" "),e("p",[a._v("在昨天討論交易(Transaction)的時候,想必最後的三個欄位「燃料單位上限(GasLimit)」、「每單位燃料的優先價格上限(MaxPriorityFeePerGas)」、「每單位燃料的價格上限(MaxFeePerGas)」讓大家覺得很困惑吧。")]),a._v(" "),e("p",[a._v("今天就讓我們來介紹燃料(Gas)與手續費(Fee)的機制。")]),a._v(" "),e("h2",{attrs:{id:"燃料-gas"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#燃料-gas"}},[a._v("#")]),a._v(" 燃料(Gas)")]),a._v(" "),e("p",[a._v("在以太坊(Ethereum)上的所有交易實際上都是在「執行特定的操作」,對狀態進行改變(如:帳戶餘額的轉移、部署新合約、與合約互動等)。而進行這些操作自然就會對節點與網路產生「運算資源的消耗」。")]),a._v(" "),e("p",[a._v("基於使用者付費的原則,發起交易的帳戶便需要為了這些「運算資源」來支付手續費。")]),a._v(" "),e("p",[a._v("燃料(Gas)便是一種用來表達「被消耗的運算資源」的單位。")]),a._v(" "),e("p",[a._v("或許你會有個疑問,在電腦或手機上執行軟體,不是都通過消耗的電(瓦特*小時)、或者佔用的運算資源(佔用 CPU 多少執行時間、使用多少記憶體等)來進行計費嗎?為什麼到了以太坊上變成一個奇怪的單位。\n這是因為節點並不是執行在「完全相同型號的機器上」,任何人只要滿足運行節點的最低標準需求,便可以在任何的電腦設備(包含但不限於:桌上型電腦、筆記型電腦、開發版、迷你電腦、手機等)上運行。因此幾乎不可能通過硬體規格來進行消耗運算資源的估價。")]),a._v(" "),e("p",[a._v("為了解決這個問題,以太坊設計了以太坊虛擬機(Ethereum Virtual Machine,簡稱 EVM),將所有運算資源抽象化,對每一種指令的操作都明定價碼,因此便能統一評估「被消耗的運算資源」囉!\n關於 EVM 我們會在後續的章節有更深的探討,這邊就暫時不展開了。")]),a._v(" "),e("h2",{attrs:{id:"燃料數量上限-gaslimit"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#燃料數量上限-gaslimit"}},[a._v("#")]),a._v(" 燃料數量上限(GasLimit)")]),a._v(" "),e("p",[a._v("燃料數量上限(GasLimit)是指在一筆交易中,發起者願意支付的最大燃料數量上限。")]),a._v(" "),e("p",[a._v("請特別留意,執行越多的操作將會需要燃燒更多的燃料 。因此在部署合約或者與合約互動時,通常需要將這個數字設定的高一些,以支付足夠的數量來讓交易能夠完成。")]),a._v(" "),e("p",[a._v("另外,如果只有轉移 Ether 給其他帳戶,這個操作需要 21,000 單位的燃料作為燃料數量上限。")]),a._v(" "),e("h3",{attrs:{id:"以轉帳為例"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#以轉帳為例"}},[a._v("#")]),a._v(" 以轉帳為例")]),a._v(" "),e("p",[a._v("假設 Alice 要轉給 Bob 一顆 Ether,Alice 將這筆交易的 gas limit 設定為 40,000。而一筆轉移 Ether 的操作需要燃燒 21,000 單位。在執行完轉帳以後,Alice 將會收到一筆 (40,000 - 21,000) = 19,000 單位的燃料退款。")]),a._v(" "),e("p",[a._v("反之,Alice 太過於小氣,只把 gas limit 設定成 10,000 單位,將導致燃料不夠用的情況,此時這筆交易將會失敗,並被標記成 "),e("code",[a._v("revert")]),a._v(" 的狀態,也不會有任何燃料被退回。")]),a._v(" "),e("h2",{attrs:{id:"改變計價模式的倫敦升級-london-upgrade"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#改變計價模式的倫敦升級-london-upgrade"}},[a._v("#")]),a._v(" 改變計價模式的倫敦升級(London Upgrade)")]),a._v(" "),e("p",[a._v("以太坊在倫敦升級時改變了燃料相關的計價模式,由於此處可以展開的範圍過大,讓我們下一章節再來討論,以下將以升級後的現在進行說明。")]),a._v(" "),e("h2",{attrs:{id:"基礎費用-base-fee"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#基礎費用-base-fee"}},[a._v("#")]),a._v(" 基礎費用(Base Fee)")]),a._v(" "),e("p",[a._v("每個區塊都有基礎費用,當發送者要發出交易時,設定的基礎費用不得低於該區塊的基礎費用。")]),a._v(" "),e("p",[a._v("請注意,這個基礎費用是通過一個公式進行計算的,其數值與前一個區塊所消耗掉的燃料數量有關。細節我們等倫敦升級章節再行探討。")]),a._v(" "),e("p",[a._v("當一筆交易被收入區塊中,這筆基礎費用將會直接燒毀,永遠地消失在這世界上。")]),a._v(" "),e("p",[a._v("燒到的手續費=基礎費用*使用掉的燃料數量。")]),a._v(" "),e("h2",{attrs:{id:"優先費用-priority-fee"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#優先費用-priority-fee"}},[a._v("#")]),a._v(" 優先費用(Priority Fee)")]),a._v(" "),e("p",[a._v("這是個資本主義的世界,就像去迪士尼樂園一樣,不想和其他人一起排隊,可以購買快速通行券來加速搭乘遊樂設施,通過課金來升級體驗。")]),a._v(" "),e("p",[a._v("在以太坊的世界也一樣,當每筆交易都支付一樣的單位費用時,人人平等,全部慢慢排隊,但也可以通過付點小費給礦工,讓礦工優先將交易放入區塊中,這個機制就是優先費用。")]),a._v(" "),e("p",[a._v("跟基礎費用不同的是,優先費用所產生的手續費會全部交給礦工。")]),a._v(" "),e("p",[a._v("給礦工的小費=優先費用*使用掉的燃料數量。")]),a._v(" "),e("h2",{attrs:{id:"單位燃料費用上限-max-fee"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#單位燃料費用上限-max-fee"}},[a._v("#")]),a._v(" 單位燃料費用上限(Max Fee)")]),a._v(" "),e("p",[a._v("對於使用者而言,每次發送交易都要設定基礎費用與優先費用是非常繁瑣的,為了提升體驗,因此衍生出單位燃料費用上限的概念。")]),a._v(" "),e("p",[a._v("單位燃料費用上限=基礎費用+優先費用")]),a._v(" "),e("p",[a._v("而基礎費用又是由公式與前一個區塊狀況而定,使用者無法自行決定,因此對於使用者而言,只需要設定「單位燃料上限」,發起交易的工具就會自動幫忙計算出「優先費用」了。")]),a._v(" "),e("h2",{attrs:{id:"手續費-fee"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#手續費-fee"}},[a._v("#")]),a._v(" 手續費(Fee)")]),a._v(" "),e("p",[a._v("總手續費=單位燃料費(Max Fee)*使用的燃料數量(Used Gas)。")]),a._v(" "),e("p",[a._v("當使用掉的燃數量將大於燃料數量上限時,交易將會失敗,此時的使用掉的燃料數量就會剛好等於燃料數量上限。")])])}),[],!1,null,null,null);e.default=_.exports}}]); \ No newline at end of file diff --git a/assets/js/27.eb393f01.js b/assets/js/27.1749641b.js similarity index 98% rename from assets/js/27.eb393f01.js rename to assets/js/27.1749641b.js index 778b94b..bab77b7 100644 --- a/assets/js/27.eb393f01.js +++ b/assets/js/27.1749641b.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[27],{350:function(t,a,v){"use strict";v.r(a);var _=v(17),e=Object(_.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"帳戶-account"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#帳戶-account"}},[t._v("#")]),t._v(" 帳戶(Account)")]),t._v(" "),a("p",[t._v("以太坊的帳戶有兩種不同的模式,以產生帳戶的方式來區分:")]),t._v(" "),a("ol",[a("li",[t._v("以私鑰(Private Key)產生的 EOA (Externally-owned account)")]),t._v(" "),a("li",[t._v("以部署合約(Deploy Contract)產生的合約帳戶(Contract account)")])]),t._v(" "),a("h2",{attrs:{id:"帳戶的共通特性"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#帳戶的共通特性"}},[t._v("#")]),t._v(" 帳戶的共通特性")]),t._v(" "),a("p",[t._v("值得注意的是,不論通過何種方式產生帳戶,都具備有以下的特性:")]),t._v(" "),a("ul",[a("li",[t._v("具備餘額(Balance)的資訊,因此可以持有與收發 Ether。")]),t._v(" "),a("li",[t._v("具備呼叫(Call)的能力,因此可以與智能合約進行互動。")])]),t._v(" "),a("h2",{attrs:{id:"eoa-externally-owned-account"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#eoa-externally-owned-account"}},[t._v("#")]),t._v(" EOA (Externally-owned account)")]),t._v(" "),a("p",[t._v("建立一個 EOA 就像是我們去銀行開戶一樣,會建議一個個人的帳戶資訊。只要你擁有私鑰,就能控制這組帳戶。")]),t._v(" "),a("p",[t._v("EOA 具備以下資訊:")]),t._v(" "),a("ol",[a("li",[t._v("餘額(Balance):用以儲存該帳戶的 Ether 數量。")]),t._v(" "),a("li",[t._v("Nonce:用以記錄該帳戶已經發出的交易(Transaction)數量")])]),t._v(" "),a("p",[t._v("EOA 可以:")]),t._v(" "),a("ol",[a("li",[t._v("收發 Ether。")]),t._v(" "),a("li",[t._v("可以發起交易(Transaction),請特別注意,由於發起交易時一定需要有發送者的簽名(Signature),因此是沒辦法直接使用智能合約發起交易的,整個交易鏈的發起者必然為一個 EOA。")])]),t._v(" "),a("h2",{attrs:{id:"合約帳戶-contract-account"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#合約帳戶-contract-account"}},[t._v("#")]),t._v(" 合約帳戶(Contract account)")]),t._v(" "),a("p",[t._v("建立合約需要使用 EOA 進行合約的部署。\n建立時需要支付燃料,因為部署合約需要在以太坊上儲存合約的程式碼與寫入合約的儲存空間。")]),t._v(" "),a("p",[t._v("合約帳戶具備以下資訊:")]),t._v(" "),a("ol",[a("li",[t._v("餘額(Balance):用以儲存該合約持有的 Ether 數量。")]),t._v(" "),a("li",[t._v("Nonce:為該帳戶建立新合約的數量。")]),t._v(" "),a("li",[t._v("合約的程式碼雜湊值(codeHash):為一組雜湊值,用以查詢資料庫中該帳戶所代表的 EVM 程式碼。")]),t._v(" "),a("li",[t._v("合約的儲存空間雜湊值(storageRoot 或者 storageHash):為一個 256 位元長度的雜湊值,代表儲存 Merkle Patricia trie 的根節點雜湊值。")])]),t._v(" "),a("p",[t._v("合約帳戶可以:")]),t._v(" "),a("ol",[a("li",[t._v("收發 Ether。")]),t._v(" "),a("li",[t._v("只有被 EOA 驅動時,才能當為交易的中繼者,進行合約部署或發送交易。")])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[27],{348:function(t,a,v){"use strict";v.r(a);var _=v(17),e=Object(_.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"帳戶-account"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#帳戶-account"}},[t._v("#")]),t._v(" 帳戶(Account)")]),t._v(" "),a("p",[t._v("以太坊的帳戶有兩種不同的模式,以產生帳戶的方式來區分:")]),t._v(" "),a("ol",[a("li",[t._v("以私鑰(Private Key)產生的 EOA (Externally-owned account)")]),t._v(" "),a("li",[t._v("以部署合約(Deploy Contract)產生的合約帳戶(Contract account)")])]),t._v(" "),a("h2",{attrs:{id:"帳戶的共通特性"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#帳戶的共通特性"}},[t._v("#")]),t._v(" 帳戶的共通特性")]),t._v(" "),a("p",[t._v("值得注意的是,不論通過何種方式產生帳戶,都具備有以下的特性:")]),t._v(" "),a("ul",[a("li",[t._v("具備餘額(Balance)的資訊,因此可以持有與收發 Ether。")]),t._v(" "),a("li",[t._v("具備呼叫(Call)的能力,因此可以與智能合約進行互動。")])]),t._v(" "),a("h2",{attrs:{id:"eoa-externally-owned-account"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#eoa-externally-owned-account"}},[t._v("#")]),t._v(" EOA (Externally-owned account)")]),t._v(" "),a("p",[t._v("建立一個 EOA 就像是我們去銀行開戶一樣,會建議一個個人的帳戶資訊。只要你擁有私鑰,就能控制這組帳戶。")]),t._v(" "),a("p",[t._v("EOA 具備以下資訊:")]),t._v(" "),a("ol",[a("li",[t._v("餘額(Balance):用以儲存該帳戶的 Ether 數量。")]),t._v(" "),a("li",[t._v("Nonce:用以記錄該帳戶已經發出的交易(Transaction)數量")])]),t._v(" "),a("p",[t._v("EOA 可以:")]),t._v(" "),a("ol",[a("li",[t._v("收發 Ether。")]),t._v(" "),a("li",[t._v("可以發起交易(Transaction),請特別注意,由於發起交易時一定需要有發送者的簽名(Signature),因此是沒辦法直接使用智能合約發起交易的,整個交易鏈的發起者必然為一個 EOA。")])]),t._v(" "),a("h2",{attrs:{id:"合約帳戶-contract-account"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#合約帳戶-contract-account"}},[t._v("#")]),t._v(" 合約帳戶(Contract account)")]),t._v(" "),a("p",[t._v("建立合約需要使用 EOA 進行合約的部署。\n建立時需要支付燃料,因為部署合約需要在以太坊上儲存合約的程式碼與寫入合約的儲存空間。")]),t._v(" "),a("p",[t._v("合約帳戶具備以下資訊:")]),t._v(" "),a("ol",[a("li",[t._v("餘額(Balance):用以儲存該合約持有的 Ether 數量。")]),t._v(" "),a("li",[t._v("Nonce:為該帳戶建立新合約的數量。")]),t._v(" "),a("li",[t._v("合約的程式碼雜湊值(codeHash):為一組雜湊值,用以查詢資料庫中該帳戶所代表的 EVM 程式碼。")]),t._v(" "),a("li",[t._v("合約的儲存空間雜湊值(storageRoot 或者 storageHash):為一個 256 位元長度的雜湊值,代表儲存 Merkle Patricia trie 的根節點雜湊值。")])]),t._v(" "),a("p",[t._v("合約帳戶可以:")]),t._v(" "),a("ol",[a("li",[t._v("收發 Ether。")]),t._v(" "),a("li",[t._v("只有被 EOA 驅動時,才能當為交易的中繼者,進行合約部署或發送交易。")])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/29.5e017797.js b/assets/js/29.2e878408.js similarity index 97% rename from assets/js/29.5e017797.js rename to assets/js/29.2e878408.js index 94db69d..b47008c 100644 --- a/assets/js/29.5e017797.js +++ b/assets/js/29.2e878408.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[29],{348:function(t,r,a){"use strict";a.r(r);var v=a(17),_=Object(v.a)({},(function(){var t=this,r=t._self._c;return r("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[r("h1",{attrs:{id:"共識機制"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#共識機制"}},[t._v("#")]),t._v(" 共識機制")]),t._v(" "),r("p",[t._v("在區塊鏈系統中,通常是由一個龐大數量的節點所構成的網路系統。\n然而,在一個分散系統中,我們無法得知有多少惡意的攻擊者存在,加上多個節點同時間可能收到來自世界各地無數的交易。若沒有一套機制來確保交易的順序、安全性、穩定性、與容錯能力,那整個系統便失去意義了。")]),t._v(" "),r("p",[t._v("因此,共識機制就被設計出來解決這個難題。")]),t._v(" "),r("h2",{attrs:{id:"共識的概念"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#共識的概念"}},[t._v("#")]),t._v(" 共識的概念")]),t._v(" "),r("p",[t._v("選舉就是一種共識機制,比如今年火熱無比的縣市長選舉,要選出市長,自然就需要選民們進行投票,而投完票後,以「票多的贏,票少的輸」的策略,決定出誰最終成為市長。")]),t._v(" "),r("p",[t._v("而在以太坊中,至少需要有 66% 的節點同意以後才能建立共識。")]),t._v(" "),r("h2",{attrs:{id:"共識機制-2"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#共識機制-2"}},[t._v("#")]),t._v(" 共識機制")]),t._v(" "),r("p",[t._v("共識機制就是一套規則,定義了在什麼樣的條件或限制下,讓整個網路都同意某個共識的方法。")]),t._v(" "),r("p",[t._v("共識機制通常定義了:")]),t._v(" "),r("ol",[r("li",[t._v("誰能參與成為礦工(Miner)或驗證者(Validator),作為挖出區塊或者驗證區塊的人,將獲得出塊獎勵以激勵大家參與。")]),t._v(" "),r("li",[t._v("如果有人作惡,應該如何被懲罰。")]),t._v(" "),r("li",[t._v("讓作惡的成本變得非常高,以避免惡意人士的攻擊。")])]),t._v(" "),r("p",[t._v("以太坊在 The Merge 之前跟比特幣(Bitcoin)一樣,都是工作量證明(Proof-of-Work)的共識機制。")]),t._v(" "),r("p",[t._v("而在 The Merge 後已經改為權益證明(Proof-of-Stake)的共識機制。")]),t._v(" "),r("h2",{attrs:{id:"不同的共識機制"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#不同的共識機制"}},[t._v("#")]),t._v(" 不同的共識機制")]),t._v(" "),r("p",[t._v("在接下來的幾個章節,我們會依序介紹什麼是工作量證明(Ethereum 1.0 的共識機制)與權益證明(Ethereum 2.0 的共識機制)")])])}),[],!1,null,null,null);r.default=_.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[29],{350:function(t,r,a){"use strict";a.r(r);var v=a(17),_=Object(v.a)({},(function(){var t=this,r=t._self._c;return r("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[r("h1",{attrs:{id:"共識機制"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#共識機制"}},[t._v("#")]),t._v(" 共識機制")]),t._v(" "),r("p",[t._v("在區塊鏈系統中,通常是由一個龐大數量的節點所構成的網路系統。\n然而,在一個分散系統中,我們無法得知有多少惡意的攻擊者存在,加上多個節點同時間可能收到來自世界各地無數的交易。若沒有一套機制來確保交易的順序、安全性、穩定性、與容錯能力,那整個系統便失去意義了。")]),t._v(" "),r("p",[t._v("因此,共識機制就被設計出來解決這個難題。")]),t._v(" "),r("h2",{attrs:{id:"共識的概念"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#共識的概念"}},[t._v("#")]),t._v(" 共識的概念")]),t._v(" "),r("p",[t._v("選舉就是一種共識機制,比如今年火熱無比的縣市長選舉,要選出市長,自然就需要選民們進行投票,而投完票後,以「票多的贏,票少的輸」的策略,決定出誰最終成為市長。")]),t._v(" "),r("p",[t._v("而在以太坊中,至少需要有 66% 的節點同意以後才能建立共識。")]),t._v(" "),r("h2",{attrs:{id:"共識機制-2"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#共識機制-2"}},[t._v("#")]),t._v(" 共識機制")]),t._v(" "),r("p",[t._v("共識機制就是一套規則,定義了在什麼樣的條件或限制下,讓整個網路都同意某個共識的方法。")]),t._v(" "),r("p",[t._v("共識機制通常定義了:")]),t._v(" "),r("ol",[r("li",[t._v("誰能參與成為礦工(Miner)或驗證者(Validator),作為挖出區塊或者驗證區塊的人,將獲得出塊獎勵以激勵大家參與。")]),t._v(" "),r("li",[t._v("如果有人作惡,應該如何被懲罰。")]),t._v(" "),r("li",[t._v("讓作惡的成本變得非常高,以避免惡意人士的攻擊。")])]),t._v(" "),r("p",[t._v("以太坊在 The Merge 之前跟比特幣(Bitcoin)一樣,都是工作量證明(Proof-of-Work)的共識機制。")]),t._v(" "),r("p",[t._v("而在 The Merge 後已經改為權益證明(Proof-of-Stake)的共識機制。")]),t._v(" "),r("h2",{attrs:{id:"不同的共識機制"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#不同的共識機制"}},[t._v("#")]),t._v(" 不同的共識機制")]),t._v(" "),r("p",[t._v("在接下來的幾個章節,我們會依序介紹什麼是工作量證明(Ethereum 1.0 的共識機制)與權益證明(Ethereum 2.0 的共識機制)")])])}),[],!1,null,null,null);r.default=_.exports}}]); \ No newline at end of file diff --git a/assets/js/35.ec1d48ed.js b/assets/js/35.8e5a422e.js similarity index 99% rename from assets/js/35.ec1d48ed.js rename to assets/js/35.8e5a422e.js index c08ea56..ad5779e 100644 --- a/assets/js/35.ec1d48ed.js +++ b/assets/js/35.8e5a422e.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[35],{357:function(a,e,s){"use strict";s.r(e);var t=s(17),r=Object(t.a)({},(function(){var a=this,e=a._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h1",{attrs:{id:"erc20-代幣標準"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#erc20-代幣標準"}},[a._v("#")]),a._v(" ERC20 代幣標準")]),a._v(" "),e("p",[a._v("ERC20 標準: https://eips.ethereum.org/EIPS/eip-20")]),a._v(" "),e("p",[a._v("在很多應用場景下,開發者需要發行自己的代幣以提供服務,比如說:遊戲代幣、點數卡、或通用貨幣。因此,這個介面標準包含了如何發行代幣、代幣間如何轉移、授權給第三方使用等概念。")]),a._v(" "),e("h2",{attrs:{id:"代幣規範"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#代幣規範"}},[a._v("#")]),a._v(" 代幣規範")]),a._v(" "),e("h3",{attrs:{id:"函式"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#函式"}},[a._v("#")]),a._v(" 函式")]),a._v(" "),e("p",[a._v("請注意,呼叫者必須處理呼叫失敗的情況,比如說轉帳可能會失敗。千萬不能假設呼叫一定會成功而忽略了函式的回傳值。")]),a._v(" "),e("h4",{attrs:{id:"name-代幣名稱-可選用"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#name-代幣名稱-可選用"}},[a._v("#")]),a._v(" name(代幣名稱),可選用")]),a._v(" "),e("p",[a._v("回傳代幣的名稱,比如:"),e("code",[a._v('"海帶作幣"')]),a._v("。")]),a._v(" "),e("p",[a._v("此函式只用來增加可用性,比如方便錢包或交易所查詢代幣名稱;由於是可選用的函式,因此不能預設每個 ERC20 的合約都實作了這個功能。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 沒有任何輸入參數,直接回傳代幣名稱(字串型態)\nfunction name() public view returns (string)\n")])])]),e("h4",{attrs:{id:"symbol-簡稱-可選用"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#symbol-簡稱-可選用"}},[a._v("#")]),a._v(" symbol(簡稱),可選用")]),a._v(" "),e("p",[a._v("回傳代幣的簡稱,比如:"),e("code",[a._v('"HDT"')])]),a._v(" "),e("p",[a._v("此函式只用來增加可用性,比如方便錢包或交易所查詢代幣簡稱;由於是可選用的函式,因此不能預設每個 ERC20 的合約都實作了這個功能。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 沒有任何輸入參數,直接回傳代幣簡稱(字串型態)\nfunction symbol() public view returns (string)\n")])])]),e("h4",{attrs:{id:"decimals-小數點-可選用"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#decimals-小數點-可選用"}},[a._v("#")]),a._v(" decimals(小數點),可選用")]),a._v(" "),e("p",[a._v("回傳該代幣的小數點位置。假設為 "),e("code",[a._v("N")]),a._v(" ,則代表代幣數量除以 (10^N) 才是基本單位,低於 N 位數的為小數後數字。")]),a._v(" "),e("p",[a._v("此函式只用來增加可用性,比如方便錢包或交易所查詢代幣的小數點位置;由於是可選用的函式,因此不能預設每個 ERC20 的合約都實作了這個功能。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 沒有任何輸入參數,直接回傳代幣小數點位置(uint8 型態)\nfunction decimals() public view returns (uint8)\n")])])]),e("h4",{attrs:{id:"totalsupply-發行總量"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#totalsupply-發行總量"}},[a._v("#")]),a._v(" totalSupply(發行總量)")]),a._v(" "),e("p",[a._v("回傳該代幣的發行總量。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 沒有任何輸入參數,直接回傳代幣小數點位置(uint256 型態)\nfunction totalSupply() public view returns (uint256)\n")])])]),e("h4",{attrs:{id:"balanceof-回傳某個帳戶的餘額"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#balanceof-回傳某個帳戶的餘額"}},[a._v("#")]),a._v(" balanceOf(回傳某個帳戶的餘額)")]),a._v(" "),e("p",[a._v("回傳 "),e("code",[a._v("_owner")]),a._v(" 的帳戶代幣餘額。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 輸入查詢者的位址 _owner,回傳其代幣餘額 balance\nfunction balanceOf(address _owner) public view returns (uint256 balance)\n")])])]),e("h4",{attrs:{id:"transfer-轉帳"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#transfer-轉帳"}},[a._v("#")]),a._v(" transfer(轉帳)")]),a._v(" "),e("p",[a._v("轉移 "),e("code",[a._v("_value")]),a._v(" 數量的代幣從「函式呼叫者」到「接收者 "),e("code",[a._v("_to")]),a._v("」,且本函式必然觸發 "),e("code",[a._v("Transfer")]),a._v(" 事件。\n當「函式呼叫者」的餘額不足時,應丟出錯誤("),e("code",[a._v("throw")]),a._v(")。")]),a._v(" "),e("p",[a._v("要留意的是,當 "),e("code",[a._v("_value")]),a._v(" 為 "),e("code",[a._v("0")]),a._v(" 時,也是個合法的轉帳,只是他轉了個寂寞。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 從 msg.sender 轉帳 _value 數量的代幣給 _to,如果成功回傳 true,失敗則回傳 false。\nfunction transfer(address _to, uint256 _value) public returns (bool success)\n")])])]),e("h4",{attrs:{id:"transferfrom-從他人處轉帳"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#transferfrom-從他人處轉帳"}},[a._v("#")]),a._v(" transferFrom(從他人處轉帳)")]),a._v(" "),e("p",[a._v("當有被授權的額度時,這個函式就是用來花掉別人的代幣的。\n轉帳 "),e("code",[a._v("_value")]),a._v(" 數量的代幣,從發送者 "),e("code",[a._v("_from")]),a._v(" ,到接收者 "),e("code",[a._v("_to")]),a._v("。並且觸發 "),e("code",[a._v("Transfer")]),a._v(" 事件。")]),a._v(" "),e("p",[a._v("這個函式在授權(approve)第三方合約或帳戶後觸發,便能允許他人動用你的額度。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 從授權者 _from 發送 _value 數量的代幣給接收者 _to,回傳值為成功與否(bool)\nfunction transferFrom(address _from, address _to, uint256 _value) public returns (bool success)\n")])])]),e("h4",{attrs:{id:"approve-授權"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#approve-授權"}},[a._v("#")]),a._v(" approve(授權)")]),a._v(" "),e("p",[a._v("呼叫者授權給花費者 "),e("code",[a._v("_spender")]),a._v(" 可動用的額度 "),e("code",[a._v("_value")]),a._v("。")]),a._v(" "),e("p",[a._v("若被再次呼叫,則新的額度 "),e("code",[a._v("_value")]),a._v(" 會直接覆蓋掉舊的額度。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 函式呼叫者 msg.sender 授權給花費者 _spender 額度 _value,回傳成功與否(bool)\nfunction approve(address _spender, uint256 _value) public returns (bool success)\n")])])]),e("h4",{attrs:{id:"allowance-授權的額度"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#allowance-授權的額度"}},[a._v("#")]),a._v(" allowance(授權的額度)")]),a._v(" "),e("p",[a._v("查詢授權者 "),e("code",[a._v("_owner")]),a._v(" 授權給花費者 "),e("code",[a._v("_spender")]),a._v(" 的剩餘使用額度。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 查詢時需給定授權者 _owner 與花費者 _spender,回傳剩餘的額度(uint256)\nfunction allowance(address _owner, address _spender) public view returns (uint256 remaining)\n")])])]),e("h3",{attrs:{id:"事件-events"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#事件-events"}},[a._v("#")]),a._v(" 事件(Events)")]),a._v(" "),e("h4",{attrs:{id:"轉帳-transfer"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#轉帳-transfer"}},[a._v("#")]),a._v(" 轉帳(Transfer)")]),a._v(" "),e("p",[a._v("當代幣發生轉移時,此事件必須被觸發,不論轉移的代幣數量有多少。")]),a._v(" "),e("p",[a._v("當一個代幣合約產生新的代幣時,需要觸發轉帳事件,其中發送者位址("),e("code",[a._v("_from")]),a._v(")被設定成("),e("code",[a._v("0x0")]),a._v(")")]),a._v(" "),e("p",[e("code",[a._v("_from")]),a._v(":發送者位址,address\n"),e("code",[a._v("_to")]),a._v(":接收者位址,address\n"),e("code",[a._v("_value")]),a._v(":轉帳的數量,uint256")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("event Transfer(address indexed _from, address indexed _to, uint256 _value)\n")])])]),e("h4",{attrs:{id:"授權-approval"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#授權-approval"}},[a._v("#")]),a._v(" 授權(Approval)")]),a._v(" "),e("p",[a._v("當成功呼叫 "),e("code",[a._v("approve(address _spender, uint256 _value)")]),a._v(" 時,必須觸發授權事件。")]),a._v(" "),e("p",[e("code",[a._v("_owner")]),a._v(":代幣擁有者,address\n"),e("code",[a._v("_spender")]),a._v(":被授權的花費者,address\n"),e("code",[a._v("_value")]),a._v(":被授權的可花費額度,uint256")]),a._v(" "),e("div",{staticClass:"language-js extra-class"},[e("pre",{pre:!0,attrs:{class:"language-js"}},[e("code",[a._v("event "),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Approval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("address indexed _owner"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" address indexed _spender"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" uint256 _value"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v("\n")])])])])}),[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[35],{356:function(a,e,s){"use strict";s.r(e);var t=s(17),r=Object(t.a)({},(function(){var a=this,e=a._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h1",{attrs:{id:"erc20-代幣標準"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#erc20-代幣標準"}},[a._v("#")]),a._v(" ERC20 代幣標準")]),a._v(" "),e("p",[a._v("ERC20 標準: https://eips.ethereum.org/EIPS/eip-20")]),a._v(" "),e("p",[a._v("在很多應用場景下,開發者需要發行自己的代幣以提供服務,比如說:遊戲代幣、點數卡、或通用貨幣。因此,這個介面標準包含了如何發行代幣、代幣間如何轉移、授權給第三方使用等概念。")]),a._v(" "),e("h2",{attrs:{id:"代幣規範"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#代幣規範"}},[a._v("#")]),a._v(" 代幣規範")]),a._v(" "),e("h3",{attrs:{id:"函式"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#函式"}},[a._v("#")]),a._v(" 函式")]),a._v(" "),e("p",[a._v("請注意,呼叫者必須處理呼叫失敗的情況,比如說轉帳可能會失敗。千萬不能假設呼叫一定會成功而忽略了函式的回傳值。")]),a._v(" "),e("h4",{attrs:{id:"name-代幣名稱-可選用"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#name-代幣名稱-可選用"}},[a._v("#")]),a._v(" name(代幣名稱),可選用")]),a._v(" "),e("p",[a._v("回傳代幣的名稱,比如:"),e("code",[a._v('"海帶作幣"')]),a._v("。")]),a._v(" "),e("p",[a._v("此函式只用來增加可用性,比如方便錢包或交易所查詢代幣名稱;由於是可選用的函式,因此不能預設每個 ERC20 的合約都實作了這個功能。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 沒有任何輸入參數,直接回傳代幣名稱(字串型態)\nfunction name() public view returns (string)\n")])])]),e("h4",{attrs:{id:"symbol-簡稱-可選用"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#symbol-簡稱-可選用"}},[a._v("#")]),a._v(" symbol(簡稱),可選用")]),a._v(" "),e("p",[a._v("回傳代幣的簡稱,比如:"),e("code",[a._v('"HDT"')])]),a._v(" "),e("p",[a._v("此函式只用來增加可用性,比如方便錢包或交易所查詢代幣簡稱;由於是可選用的函式,因此不能預設每個 ERC20 的合約都實作了這個功能。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 沒有任何輸入參數,直接回傳代幣簡稱(字串型態)\nfunction symbol() public view returns (string)\n")])])]),e("h4",{attrs:{id:"decimals-小數點-可選用"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#decimals-小數點-可選用"}},[a._v("#")]),a._v(" decimals(小數點),可選用")]),a._v(" "),e("p",[a._v("回傳該代幣的小數點位置。假設為 "),e("code",[a._v("N")]),a._v(" ,則代表代幣數量除以 (10^N) 才是基本單位,低於 N 位數的為小數後數字。")]),a._v(" "),e("p",[a._v("此函式只用來增加可用性,比如方便錢包或交易所查詢代幣的小數點位置;由於是可選用的函式,因此不能預設每個 ERC20 的合約都實作了這個功能。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 沒有任何輸入參數,直接回傳代幣小數點位置(uint8 型態)\nfunction decimals() public view returns (uint8)\n")])])]),e("h4",{attrs:{id:"totalsupply-發行總量"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#totalsupply-發行總量"}},[a._v("#")]),a._v(" totalSupply(發行總量)")]),a._v(" "),e("p",[a._v("回傳該代幣的發行總量。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 沒有任何輸入參數,直接回傳代幣小數點位置(uint256 型態)\nfunction totalSupply() public view returns (uint256)\n")])])]),e("h4",{attrs:{id:"balanceof-回傳某個帳戶的餘額"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#balanceof-回傳某個帳戶的餘額"}},[a._v("#")]),a._v(" balanceOf(回傳某個帳戶的餘額)")]),a._v(" "),e("p",[a._v("回傳 "),e("code",[a._v("_owner")]),a._v(" 的帳戶代幣餘額。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 輸入查詢者的位址 _owner,回傳其代幣餘額 balance\nfunction balanceOf(address _owner) public view returns (uint256 balance)\n")])])]),e("h4",{attrs:{id:"transfer-轉帳"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#transfer-轉帳"}},[a._v("#")]),a._v(" transfer(轉帳)")]),a._v(" "),e("p",[a._v("轉移 "),e("code",[a._v("_value")]),a._v(" 數量的代幣從「函式呼叫者」到「接收者 "),e("code",[a._v("_to")]),a._v("」,且本函式必然觸發 "),e("code",[a._v("Transfer")]),a._v(" 事件。\n當「函式呼叫者」的餘額不足時,應丟出錯誤("),e("code",[a._v("throw")]),a._v(")。")]),a._v(" "),e("p",[a._v("要留意的是,當 "),e("code",[a._v("_value")]),a._v(" 為 "),e("code",[a._v("0")]),a._v(" 時,也是個合法的轉帳,只是他轉了個寂寞。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 從 msg.sender 轉帳 _value 數量的代幣給 _to,如果成功回傳 true,失敗則回傳 false。\nfunction transfer(address _to, uint256 _value) public returns (bool success)\n")])])]),e("h4",{attrs:{id:"transferfrom-從他人處轉帳"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#transferfrom-從他人處轉帳"}},[a._v("#")]),a._v(" transferFrom(從他人處轉帳)")]),a._v(" "),e("p",[a._v("當有被授權的額度時,這個函式就是用來花掉別人的代幣的。\n轉帳 "),e("code",[a._v("_value")]),a._v(" 數量的代幣,從發送者 "),e("code",[a._v("_from")]),a._v(" ,到接收者 "),e("code",[a._v("_to")]),a._v("。並且觸發 "),e("code",[a._v("Transfer")]),a._v(" 事件。")]),a._v(" "),e("p",[a._v("這個函式在授權(approve)第三方合約或帳戶後觸發,便能允許他人動用你的額度。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 從授權者 _from 發送 _value 數量的代幣給接收者 _to,回傳值為成功與否(bool)\nfunction transferFrom(address _from, address _to, uint256 _value) public returns (bool success)\n")])])]),e("h4",{attrs:{id:"approve-授權"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#approve-授權"}},[a._v("#")]),a._v(" approve(授權)")]),a._v(" "),e("p",[a._v("呼叫者授權給花費者 "),e("code",[a._v("_spender")]),a._v(" 可動用的額度 "),e("code",[a._v("_value")]),a._v("。")]),a._v(" "),e("p",[a._v("若被再次呼叫,則新的額度 "),e("code",[a._v("_value")]),a._v(" 會直接覆蓋掉舊的額度。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 函式呼叫者 msg.sender 授權給花費者 _spender 額度 _value,回傳成功與否(bool)\nfunction approve(address _spender, uint256 _value) public returns (bool success)\n")])])]),e("h4",{attrs:{id:"allowance-授權的額度"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#allowance-授權的額度"}},[a._v("#")]),a._v(" allowance(授權的額度)")]),a._v(" "),e("p",[a._v("查詢授權者 "),e("code",[a._v("_owner")]),a._v(" 授權給花費者 "),e("code",[a._v("_spender")]),a._v(" 的剩餘使用額度。")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("// 查詢時需給定授權者 _owner 與花費者 _spender,回傳剩餘的額度(uint256)\nfunction allowance(address _owner, address _spender) public view returns (uint256 remaining)\n")])])]),e("h3",{attrs:{id:"事件-events"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#事件-events"}},[a._v("#")]),a._v(" 事件(Events)")]),a._v(" "),e("h4",{attrs:{id:"轉帳-transfer"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#轉帳-transfer"}},[a._v("#")]),a._v(" 轉帳(Transfer)")]),a._v(" "),e("p",[a._v("當代幣發生轉移時,此事件必須被觸發,不論轉移的代幣數量有多少。")]),a._v(" "),e("p",[a._v("當一個代幣合約產生新的代幣時,需要觸發轉帳事件,其中發送者位址("),e("code",[a._v("_from")]),a._v(")被設定成("),e("code",[a._v("0x0")]),a._v(")")]),a._v(" "),e("p",[e("code",[a._v("_from")]),a._v(":發送者位址,address\n"),e("code",[a._v("_to")]),a._v(":接收者位址,address\n"),e("code",[a._v("_value")]),a._v(":轉帳的數量,uint256")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("event Transfer(address indexed _from, address indexed _to, uint256 _value)\n")])])]),e("h4",{attrs:{id:"授權-approval"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#授權-approval"}},[a._v("#")]),a._v(" 授權(Approval)")]),a._v(" "),e("p",[a._v("當成功呼叫 "),e("code",[a._v("approve(address _spender, uint256 _value)")]),a._v(" 時,必須觸發授權事件。")]),a._v(" "),e("p",[e("code",[a._v("_owner")]),a._v(":代幣擁有者,address\n"),e("code",[a._v("_spender")]),a._v(":被授權的花費者,address\n"),e("code",[a._v("_value")]),a._v(":被授權的可花費額度,uint256")]),a._v(" "),e("div",{staticClass:"language-js extra-class"},[e("pre",{pre:!0,attrs:{class:"language-js"}},[e("code",[a._v("event "),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Approval")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("address indexed _owner"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" address indexed _spender"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" uint256 _value"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v("\n")])])])])}),[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/36.7ad1a99a.js b/assets/js/36.c3b1843c.js similarity index 97% rename from assets/js/36.7ad1a99a.js rename to assets/js/36.c3b1843c.js index cd10b17..ada72c5 100644 --- a/assets/js/36.7ad1a99a.js +++ b/assets/js/36.c3b1843c.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[36],{356:function(t,a,v){"use strict";v.r(a);var _=v(17),r=Object(_.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"erc20-例子"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#erc20-例子"}},[t._v("#")]),t._v(" ERC20 例子")]),t._v(" "),a("p",[t._v("昨天文鄒鄒地把整個 ERC20 的標準給寫了一遍,然後呢?然後讀者就睡著了╮(╯▽╰)╭")]),t._v(" "),a("p",[t._v("於是今天讓我們從實際例子下手,來看看 ERC20 到底能做些什麼事情吧!")]),t._v(" "),a("h2",{attrs:{id:"穩定幣"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#穩定幣"}},[t._v("#")]),t._v(" 穩定幣")]),t._v(" "),a("p",[t._v("通貨,有些約定成俗的規則:")]),t._v(" "),a("ol",[a("li",[t._v("每個單位貨幣都是等價的,不會因為周杰倫手上的一千塊跟海帶手上的一千塊,都是一千塊。")]),t._v(" "),a("li",[t._v("標準中設定了「小數位數」,因此可以被分割,比如一角、五毛的概念;跟我們在使用 ETH 時一樣,不是每次都要轉 1 ETH,可以是 0.000001 ETH。")])]),t._v(" "),a("p",[t._v("穩定幣,跟斯斯一樣分很多種,但今天我們只在乎用美元當儲備的穩定幣,也就是他在保證金戶頭裡面存一美金,就發行一美金代幣。")]),t._v(" "),a("p",[t._v("在這樣的情況下,我們便能在區塊鏈上流通美金的代幣;如同去拉斯維加斯的賭場一樣,賭的是籌碼;在穩定幣的場景裡,我們通過在區塊鏈上流通「美金穩定幣」作為美金的虛擬通貨所使用,可以拿來買書、買 NFT 等。")]),t._v(" "),a("h2",{attrs:{id:"股票"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#股票"}},[t._v("#")]),t._v(" 股票")]),t._v(" "),a("p",[t._v("沒錯,股票其實也有類似的規則:")]),t._v(" "),a("ol",[a("li",[t._v("每個 share 都是等價的,張忠謀的一股台積電跟海帶手上的一股台積電都是等價的。不會因為他是張忠謀手上的一股就更值錢。")]),t._v(" "),a("li",[t._v("而股其實是被切割後的概念了,在以前的台灣股市交易中,我們只能買一張(等於一千股)。")])]),t._v(" "),a("p",[t._v("也因此,有人透過發行 ERC20 在區塊鏈上來當股票使用,每個買代幣的人就自動成為股東,擁有投票跟表決權。")]),t._v(" "),a("h2",{attrs:{id:"要注意的事情"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#要注意的事情"}},[t._v("#")]),t._v(" 要注意的事情")]),t._v(" "),a("p",[t._v("ERC20 代幣人人都可以發,名稱可以取一樣,簡稱也可以取一樣,因此必須很嚴格的檢查該代幣的合約位址,才能確保真的是相同的合約,不要輕易被詐騙囉!!!")])])}),[],!1,null,null,null);a.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[36],{357:function(t,a,v){"use strict";v.r(a);var _=v(17),r=Object(_.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"erc20-例子"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#erc20-例子"}},[t._v("#")]),t._v(" ERC20 例子")]),t._v(" "),a("p",[t._v("昨天文鄒鄒地把整個 ERC20 的標準給寫了一遍,然後呢?然後讀者就睡著了╮(╯▽╰)╭")]),t._v(" "),a("p",[t._v("於是今天讓我們從實際例子下手,來看看 ERC20 到底能做些什麼事情吧!")]),t._v(" "),a("h2",{attrs:{id:"穩定幣"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#穩定幣"}},[t._v("#")]),t._v(" 穩定幣")]),t._v(" "),a("p",[t._v("通貨,有些約定成俗的規則:")]),t._v(" "),a("ol",[a("li",[t._v("每個單位貨幣都是等價的,不會因為周杰倫手上的一千塊跟海帶手上的一千塊,都是一千塊。")]),t._v(" "),a("li",[t._v("標準中設定了「小數位數」,因此可以被分割,比如一角、五毛的概念;跟我們在使用 ETH 時一樣,不是每次都要轉 1 ETH,可以是 0.000001 ETH。")])]),t._v(" "),a("p",[t._v("穩定幣,跟斯斯一樣分很多種,但今天我們只在乎用美元當儲備的穩定幣,也就是他在保證金戶頭裡面存一美金,就發行一美金代幣。")]),t._v(" "),a("p",[t._v("在這樣的情況下,我們便能在區塊鏈上流通美金的代幣;如同去拉斯維加斯的賭場一樣,賭的是籌碼;在穩定幣的場景裡,我們通過在區塊鏈上流通「美金穩定幣」作為美金的虛擬通貨所使用,可以拿來買書、買 NFT 等。")]),t._v(" "),a("h2",{attrs:{id:"股票"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#股票"}},[t._v("#")]),t._v(" 股票")]),t._v(" "),a("p",[t._v("沒錯,股票其實也有類似的規則:")]),t._v(" "),a("ol",[a("li",[t._v("每個 share 都是等價的,張忠謀的一股台積電跟海帶手上的一股台積電都是等價的。不會因為他是張忠謀手上的一股就更值錢。")]),t._v(" "),a("li",[t._v("而股其實是被切割後的概念了,在以前的台灣股市交易中,我們只能買一張(等於一千股)。")])]),t._v(" "),a("p",[t._v("也因此,有人透過發行 ERC20 在區塊鏈上來當股票使用,每個買代幣的人就自動成為股東,擁有投票跟表決權。")]),t._v(" "),a("h2",{attrs:{id:"要注意的事情"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#要注意的事情"}},[t._v("#")]),t._v(" 要注意的事情")]),t._v(" "),a("p",[t._v("ERC20 代幣人人都可以發,名稱可以取一樣,簡稱也可以取一樣,因此必須很嚴格的檢查該代幣的合約位址,才能確保真的是相同的合約,不要輕易被詐騙囉!!!")])])}),[],!1,null,null,null);a.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/37.29d69bba.js b/assets/js/37.48d45ab3.js similarity index 98% rename from assets/js/37.29d69bba.js rename to assets/js/37.48d45ab3.js index 98f2ada..91f6c2e 100644 --- a/assets/js/37.29d69bba.js +++ b/assets/js/37.48d45ab3.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[37],{359:function(e,n,r){"use strict";r.r(n);var t=r(17),o=Object(t.a)({},(function(){var e=this,n=e._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[n("h1",{attrs:{id:"erc721-非同值性代幣-nft-標準"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#erc721-非同值性代幣-nft-標準"}},[e._v("#")]),e._v(" ERC721 非同值性代幣(NFT)標準")]),e._v(" "),n("p",[e._v("與 ERC20 同值性代幣不同,ERC721 的代幣不允許同值性存在,因此每個代幣都擁有一個獨一無二的編號(uint256 型態),且這組編號在合約建立到銷毀前都不應該被改變。")]),e._v(" "),n("p",[e._v("除了本質與 ERC20 不同之外,NFT 的可能使用場景可能更加複雜,比如 NFT 可以被放到一個公開交易市場上(如:"),n("a",{attrs:{href:"https://opensea.io/",target:"_blank",rel:"noopener noreferrer"}},[e._v("OpenSea"),n("OutboundLink")],1),e._v(")或其他第三方服務所持有或轉移。")]),e._v(" "),n("p",[e._v("此外,NFT 的常見使用情境有:")]),e._v(" "),n("ol",[n("li",[e._v("「對實體資產的擁有權」:將房屋權狀綁定成 NFT、把畫作綁定成 NFT 等。")]),e._v(" "),n("li",[e._v("「收藏品」:手機遊戲中常見的收集要素,比如抽角色、抽武器裝備、抽卡包等。")]),e._v(" "),n("li",[e._v("「虛擬資產」:在去中心化交易所成為流動性提供者可獲得對應的交易對的 NFT、買了 ENS 網域名稱也會獲得一個 NFT 代表該網域的所有權。")])]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("interface ERC721 {\n /// 轉移事件:當 NFT 的所有權被轉移時,觸發此事件,包含「產生(`from == 0`)」與「銷毀(to == 0)」的轉移。\n /// 發送者:`_from`\n /// 接收者:`_to`\n /// 轉移的 NFT ID:`tokenId``\n event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);\n\n /// 授權事件:當有人授權 NFT 給他人時,觸發此事件。\n /// 當轉移發生時,需要將被轉移的 NFT 中已經授權的位址清空。\n /// 持有者:`_owner`\n /// 被授權者:`_approved`\n /// 授權的 NFT ID:`tokenId``\n event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);\n\n /// 授權或撤銷事件:持有者授權或撤銷給被授權者其全部持有的 NFT 時,觸發此事件。\n /// 持有者:`_owner`\n /// 被授權者:`_operator`\n /// 授權或撤銷:`_approved`\n event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);\n\n /// 回傳該持有者(`_owner`)所持有的 NFT 數量(`uint256`)。\n function balanceOf(address _owner) external view returns (uint256);\n\n /// 回傳該 NFT(`_tokenId`) 的持有者(`address`)。\n function ownerOf(uint256 _tokenId) external view returns (address);\n\n /// 從當前持有者(`_from`)轉移 NFT (`_tokenId`) 的持有權給新持有者(`_to`),並把附加資料(`data`)一起發給新持有者。\n function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;\n\n /// 從當前持有者(`_from`)轉移 NFT (`_tokenId`) 的持有權給新持有者(`_to`)。\n function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;\n\n /// 從當前持有者(`_from`)轉移 NFT (`_tokenId`) 的持有權給新持有者(`_to`),但不檢查是否新持有者是否能接收這個 NFT。\n function transferFrom(address _from, address _to, uint256 _tokenId) external payable;\n\n /// 發送者(`msg.sender`)授權 NFT (`_tokenId`)給第三方(`_approved`)。\n function approve(address _approved, uint256 _tokenId) external payable;\n\n /// 發送者(`msg.sender`)授權或撤銷所有 NFT 給第三方(`_operator`)。\n function setApprovalForAll(address _operator, bool _approved) external;\n\n /// 檢查 NFT(`_tokenId`)的被授權者帳戶(`address`),若無被授權者,回傳 0x0。\n function getApproved(uint256 _tokenId) external view returns (address);\n\n /// 檢查持有者(`_owner`)是否授權全部的 NFT 給第三方帳戶(`_operator`)。\n function isApprovedForAll(address _owner, address _operator) external view returns (bool);\n}\n")])])])])}),[],!1,null,null,null);n.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[37],{358:function(e,n,r){"use strict";r.r(n);var t=r(17),o=Object(t.a)({},(function(){var e=this,n=e._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[n("h1",{attrs:{id:"erc721-非同值性代幣-nft-標準"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#erc721-非同值性代幣-nft-標準"}},[e._v("#")]),e._v(" ERC721 非同值性代幣(NFT)標準")]),e._v(" "),n("p",[e._v("與 ERC20 同值性代幣不同,ERC721 的代幣不允許同值性存在,因此每個代幣都擁有一個獨一無二的編號(uint256 型態),且這組編號在合約建立到銷毀前都不應該被改變。")]),e._v(" "),n("p",[e._v("除了本質與 ERC20 不同之外,NFT 的可能使用場景可能更加複雜,比如 NFT 可以被放到一個公開交易市場上(如:"),n("a",{attrs:{href:"https://opensea.io/",target:"_blank",rel:"noopener noreferrer"}},[e._v("OpenSea"),n("OutboundLink")],1),e._v(")或其他第三方服務所持有或轉移。")]),e._v(" "),n("p",[e._v("此外,NFT 的常見使用情境有:")]),e._v(" "),n("ol",[n("li",[e._v("「對實體資產的擁有權」:將房屋權狀綁定成 NFT、把畫作綁定成 NFT 等。")]),e._v(" "),n("li",[e._v("「收藏品」:手機遊戲中常見的收集要素,比如抽角色、抽武器裝備、抽卡包等。")]),e._v(" "),n("li",[e._v("「虛擬資產」:在去中心化交易所成為流動性提供者可獲得對應的交易對的 NFT、買了 ENS 網域名稱也會獲得一個 NFT 代表該網域的所有權。")])]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("interface ERC721 {\n /// 轉移事件:當 NFT 的所有權被轉移時,觸發此事件,包含「產生(`from == 0`)」與「銷毀(to == 0)」的轉移。\n /// 發送者:`_from`\n /// 接收者:`_to`\n /// 轉移的 NFT ID:`tokenId``\n event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);\n\n /// 授權事件:當有人授權 NFT 給他人時,觸發此事件。\n /// 當轉移發生時,需要將被轉移的 NFT 中已經授權的位址清空。\n /// 持有者:`_owner`\n /// 被授權者:`_approved`\n /// 授權的 NFT ID:`tokenId``\n event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);\n\n /// 授權或撤銷事件:持有者授權或撤銷給被授權者其全部持有的 NFT 時,觸發此事件。\n /// 持有者:`_owner`\n /// 被授權者:`_operator`\n /// 授權或撤銷:`_approved`\n event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);\n\n /// 回傳該持有者(`_owner`)所持有的 NFT 數量(`uint256`)。\n function balanceOf(address _owner) external view returns (uint256);\n\n /// 回傳該 NFT(`_tokenId`) 的持有者(`address`)。\n function ownerOf(uint256 _tokenId) external view returns (address);\n\n /// 從當前持有者(`_from`)轉移 NFT (`_tokenId`) 的持有權給新持有者(`_to`),並把附加資料(`data`)一起發給新持有者。\n function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;\n\n /// 從當前持有者(`_from`)轉移 NFT (`_tokenId`) 的持有權給新持有者(`_to`)。\n function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;\n\n /// 從當前持有者(`_from`)轉移 NFT (`_tokenId`) 的持有權給新持有者(`_to`),但不檢查是否新持有者是否能接收這個 NFT。\n function transferFrom(address _from, address _to, uint256 _tokenId) external payable;\n\n /// 發送者(`msg.sender`)授權 NFT (`_tokenId`)給第三方(`_approved`)。\n function approve(address _approved, uint256 _tokenId) external payable;\n\n /// 發送者(`msg.sender`)授權或撤銷所有 NFT 給第三方(`_operator`)。\n function setApprovalForAll(address _operator, bool _approved) external;\n\n /// 檢查 NFT(`_tokenId`)的被授權者帳戶(`address`),若無被授權者,回傳 0x0。\n function getApproved(uint256 _tokenId) external view returns (address);\n\n /// 檢查持有者(`_owner`)是否授權全部的 NFT 給第三方帳戶(`_operator`)。\n function isApprovedForAll(address _owner, address _operator) external view returns (bool);\n}\n")])])])])}),[],!1,null,null,null);n.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/38.74807ea4.js b/assets/js/38.7b042d65.js similarity index 99% rename from assets/js/38.74807ea4.js rename to assets/js/38.7b042d65.js index 6ebddaa..43ac34b 100644 --- a/assets/js/38.74807ea4.js +++ b/assets/js/38.7b042d65.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[38],{358:function(T,M,N){"use strict";N.r(M);var a=N(17),U=Object(a.a)({},(function(){var T=this,M=T._self._c;return M("ContentSlotsDistributor",{attrs:{"slot-key":T.$parent.slotKey}},[M("h1",{attrs:{id:"erc721-的元資料擴充-metadata-extension"}},[M("a",{staticClass:"header-anchor",attrs:{href:"#erc721-的元資料擴充-metadata-extension"}},[T._v("#")]),T._v(" ERC721 的元資料擴充(metadata extension)")]),T._v(" "),M("p",[T._v("一個 ERC721 的標準中,我們可以發現它定義了每個 NFT 對應到獨一無二的 "),M("code",[T._v("tokenId")]),T._v(",但卻沒有把每個 NFT 的實際資料儲存在合約中,這樣我們怎麼知道花了大錢買的 NFT 就是一張 JPG 圖片呢?")]),T._v(" "),M("h2",{attrs:{id:"erc721-metadata-extension"}},[M("a",{staticClass:"header-anchor",attrs:{href:"#erc721-metadata-extension"}},[T._v("#")]),T._v(" ERC721 metadata extension")]),T._v(" "),M("div",{staticClass:"language- extra-class"},[M("pre",{pre:!0,attrs:{class:"language-text"}},[M("code",[T._v("interface ERC721Metadata /* is ERC721 */ {\n /// 回傳本 NFT 系列的名稱\n function name() external view returns (string _name);\n\n /// 回傳本 NFT 系列的簡稱\n function symbol() external view returns (string _symbol);\n\n /// 回傳 URI (Uniform Resource Identifier)\n /// URI 可能指向一個代表了 ERC721 元資料 JSON 綱要的檔案\n function tokenURI(uint256 _tokenId) external view returns (string);\n}\n")])])]),M("h3",{attrs:{id:"erc721-metadata-json-schema"}},[M("a",{staticClass:"header-anchor",attrs:{href:"#erc721-metadata-json-schema"}},[T._v("#")]),T._v(" ERC721 metadata JSON schema")]),T._v(" "),M("p",[T._v("就是一個簡單的 JSON 格式,紀錄了 NFT 的名稱、簡介、與圖片。")]),T._v(" "),M("div",{staticClass:"language- extra-class"},[M("pre",{pre:!0,attrs:{class:"language-text"}},[M("code",[T._v('{\n "title": "Asset Metadata",\n "type": "object",\n "properties": {\n "name": {\n "type": "string",\n "description": "Identifies the asset to which this NFT represents"\n },\n "description": {\n "type": "string",\n "description": "Describes the asset to which this NFT represents"\n },\n "image": {\n "type": "string",\n "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive."\n }\n }\n}\n')])])]),M("h2",{attrs:{id:"以-proof-of-stake-pages-為例"}},[M("a",{staticClass:"header-anchor",attrs:{href:"#以-proof-of-stake-pages-為例"}},[T._v("#")]),T._v(" 以 Proof of Stake: Pages 為例")]),T._v(" "),M("p",[T._v("OpenSea 頁面: https://opensea.io/collection/proof-of-stake-pages\n在 etherscan 上的頁面: https://etherscan.io/address/0x5bf5bcc5362f88721167c1068b58c60cad075aac")]),T._v(" "),M("p",[T._v("這是一本由 Vitalik 寫的書,價格是自由樂捐的,他會以 NFT 的形式紀錄了捐款的證書。")]),T._v(" "),M("h3",{attrs:{id:"nft-圖片"}},[M("a",{staticClass:"header-anchor",attrs:{href:"#nft-圖片"}},[T._v("#")]),T._v(" NFT 圖片")]),T._v(" "),M("p",[T._v("比如,這就是我捐款的證明:\n"),M("img",{attrs:{src:"https://i.imgur.com/daplCPL.png",alt:""}})]),T._v(" "),M("h3",{attrs:{id:"nft-uri"}},[M("a",{staticClass:"header-anchor",attrs:{href:"#nft-uri"}},[T._v("#")]),T._v(" NFT URI")]),T._v(" "),M("p",[T._v("而我的 "),M("code",[T._v("tokenId")]),T._v(" 為 "),M("code",[T._v("59383")]),T._v(",我們可以去 etherscan 上面用 ERC721 的介面來查詢 URI 的資訊:")]),T._v(" "),M("p",[M("img",{attrs:{src:"https://i.imgur.com/C10im3R.jpg",alt:""}})]),T._v(" "),M("p",[T._v("此時可以看到他是以 JSON base64 編碼的方式儲存在上面:")]),T._v(" "),M("div",{staticClass:"language- extra-class"},[M("pre",{pre:!0,attrs:{class:"language-text"}},[M("code",[T._v("eyJzaWduZWRfdG8iOiJoeWRhaS5ldGgiLCAiZXh0ZXJuYWxfdXJsIjoiaHR0cHM6Ly9wcm9vZm9mc3Rha2UuZ2l0Y29pbi5jby8iLCAidGltZXN0YW1wIjoiMTY2MjgzMDY5MCIsICJwbGVkZ2UiOiI1MDAwMDAwMDAwMDAwMDAwMCIsICJtZXNzYWdlIjoiVGhhbmsgeW91IGZvciBzdXBwb3J0aW5nIHB1YmxpYyBnb29kcywgYW5kIGVuam95IHRoZSBib29rISIsICJpbWFnZSI6ICJkYXRhOmltYWdlL3N2Zyt4bWw7YmFzZTY0LFBITjJaeUI0Yld4dWN6MGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNakF3TUM5emRtY2lJSGRwWkhSb1BTSTJNRFl1TWlJZ2FHVnBaMmgwUFNJNE1Ua3VOQ0lnZG1sbGQwSnZlRDBpTUNBd0lEWXdOaTR5SURneE9TNDBJajQ4WkdWbWN6NDhjM1I1YkdVK0xtRjdabWxzYkRvalptWm1PMzB1WW50bWFXeHNPbTV2Ym1VN2MzUnliMnRsT2lOa09XTTRaR0k3YzNSeWIydGxMVzFwZEdWeWJHbHRhWFE2TVRBN2MzUnliMnRsTFhkcFpIUm9Pakp3ZUR0OUxtTXNMbVFzTG1Vc0xtWXNMbWNzTG1nc0xta3NMbW9zTG1zc0xtd3NMbTBzTG00c0xtOTdhWE52YkdGMGFXOXVPbWx6YjJ4aGRHVTdmUzVqTEM1a0xDNWxMQzVtTEM1bkxDNXBMQzVxTEM1cmUyWnZiblF0YzJsNlpUbzFOWEI0TzMwdVl5d3VaWHRtYVd4c09pTmxPVFppTldRN2ZTNWpMQzVrTEM1bExDNW1MQzVuTEM1cmUyWnZiblF0Wm1GdGFXeDVPa3gxYzNSRWFYTndiR0Y1TFVScFpHOXVaU3dnVEhWemRDQkVhV1J2Ym1VN2ZTNWtMQzVtZTJacGJHdzZJemxpTkdFNFpEdDlMbVY3YkdWMGRHVnlMWE53WVdOcGJtYzZNQzR3TW1WdE8zMHVabnRzWlhSMFpYSXRjM0JoWTJsdVp6b3dMakF5WlcwN2ZTNW5lMlpwYkd3Nkl6bGlOR0U0WXp0OUxtaDdabTl1ZEMxemFYcGxPalExY0hnN1ptbHNiRG9qTUdOaU5tVmhPMlp2Ym5RdFptRnRhV3g1T2t4MWMzUXRTWFJoYkdsakxDQk1kWE4wTzJadmJuUXRjM1I1YkdVNmFYUmhiR2xqTzMwdWFTd3VhM3RtYVd4c09pTTFNR0ZsTlRnN2ZTNXBMQzVxZTJadmJuUXRabUZ0YVd4NU9reDFjM1F0VW1WbmRXeGhjaXdnVEhWemREdHNaWFIwWlhJdGMzQmhZMmx1Wnpvd0xqQTFaVzA3ZlM1cWUyWnBiR3c2STJWbU9Ea3hOanQ5TG13c0xtMTdabTl1ZEMxemFYcGxPakk1TGprNWNIZzdmUzVzTEM1dWUyWnZiblF0Wm1GdGFXeDVPa0Z5YVdGc0xVSnZiR1JOVkN3Z1FYSnBZV3c3Wm05dWRDMTNaV2xuYUhRNk56QXdPMzB1YlN3dWIzdG1iMjUwTFdaaGJXbHNlVHBCY21saGJFMVVMQ0JCY21saGJEc2diV0Z5WjJsdUxXeGxablE2SUdGMWRHODdJRzFoY21kcGJpMXlhV2RvZERvZ1lYVjBienNnZDJsa2RHZzZJRFF3SlR0OUxtNTdabTl1ZEMxemFYcGxPakl3Y0hnN2ZTNXZlMlp2Ym5RdGMybDZaVG94T0hCNE8zMDhMM04wZVd4bFBqd3ZaR1ZtY3o0OGNtVmpkQ0JqYkdGemN6MGlZU0lnZDJsa2RHZzlJall3Tmk0eUlpQm9aV2xuYUhROUlqZ3hPUzQwSWk4K1BIUmxlSFFnWTJ4aGMzTTlJbTRpUGp4MGMzQmhiaUJqYkdGemN6MGliaUlnZEdWNGRDMWhibU5vYjNJOUltMXBaR1JzWlNJZ2VEMGlOVEFsSWlCNVBTSTBNaVVpUG1oNVpHRnBMbVYwYUR3dmRITndZVzQrUEM5MFpYaDBQangwWlhoMElIUnlZVzV6Wm05eWJUMGlkSEpoYm5Oc1lYUmxLRGMxSURNMU1pNDROU2tpSUdadmJuUXRjMmw2WlQwaU1UZ2lJR1p2Ym5RdFptRnRhV3g1UFNKQmNtbGhiRTFVTENCQmNtbGhiQ0krUEhSemNHRnVJSFJsZUhRdFlXNWphRzl5UFNKdGFXUmtiR1VpSUhnOUlqTTNMalVsSWlCNVBTSXlNREFpUGpFMk5qSTRNekEyT1RBOEwzUnpjR0Z1UGp4MGMzQmhiaUIwWlhoMExXRnVZMmh2Y2owaWJXbGtaR3hsSWlCNFBTSXpOeTQxSlNJZ2VUMGlNall3SWo0MU1EQXdNREF3TURBd01EQXdNREF3TUNBb2QyVnBLVHd2ZEhOd1lXNCtQSFJ6Y0dGdUlIUmxlSFF0WVc1amFHOXlQU0p0YVdSa2JHVWlJSGc5SWpNM0xqVWxJaUI1UFNJek1qQWlQakI0TldKbU5XSmpZelV6TmpKbU9EZzNNakV4Tmpkak1UQTJPR0kxT0dNMk1HTmhaREEzTldGaFl6d3ZkSE53WVc0K1BIUnpjR0Z1SUhSbGVIUXRZVzVqYUc5eVBTSnRhV1JrYkdVaUlIZzlJak0zTGpVbElpQjVQU0l4TWpBaVBpSlVhR0Z1YXlCNWIzVWdabTl5SUhOMWNIQnZjblJwYm1jZ2NIVmliR2xqSUdkdmIyUnpMQ0JoYm1RZ1pXNXFiM2tnZEdobElHSnZiMnNoSWp3dmRITndZVzQrUEhSemNHRnVJSFJsZUhRdFlXNWphRzl5UFNKdGFXUmtiR1VpSUhnOUlqTTNMalVsSWlCNVBTSXlNakFpUG0xcGJuUWdkR2x0WlhOMFlXMXdQQzkwYzNCaGJqNDhkSE53WVc0Z2RHVjRkQzFoYm1Ob2IzSTlJbTFwWkdSc1pTSWdlRDBpTXpjdU5TVWlJSGs5SWpNME1DSStZMjl1ZEhKaFkzUThMM1J6Y0dGdVBqeDBjM0JoYmlCMFpYaDBMV0Z1WTJodmNqMGliV2xrWkd4bElpQjRQU0l6Tnk0MUpTSWdlVDBpTWpnd0lqNTJZV3gxWlR3dmRITndZVzQrUEhSemNHRnVJSFJsZUhRdFlXNWphRzl5UFNKdGFXUmtiR1VpSUhnOUlqTTNMalVsSWlCNVBTSXhOREFpUGp3dmRITndZVzQrUEM5MFpYaDBQanh5WldOMElHTnNZWE56UFNKaUlpQjRQU0l5TVM0NUlpQjVQU0l4TmprdU5TSWdkMmxrZEdnOUlqVTJNaTQwSWlCb1pXbG5hSFE5SWpVMk1pNDBJaTgrUEdjZ2MzUjViR1U5SW1semIyeGhkR2x2YmpwcGMyOXNZWFJsSWo0OGNHRjBhQ0JrUFNKTk5EWXVOallzT1RndU9UTjJMUzR5T0dnMExqZzVWall3TGpjeFNEUTJMalkyZGkwdU1qaElOalV1T1RGak1USXNNQ3d4T0M0ME1pd3pMakU1TERFNExqUXlMREV4TGpFM0xEQXNPUzQwTFRFeExqYzNMREV4TGpJM0xURTVMamcxTERFeExqSTNhQzB4TGpaV09UZ3VOalZvTlM0NE0zWXVNamhhVFRZeUxqZzRMRGd5TGpab01TNDJZelV1T0RNc01DdzNMamMxTFRNdU5EY3NOeTQzTlMweE1YTXRNUzQ1TWkweE1DNDRPUzAzTGpjMUxURXdMamc1YUMweExqWmFJaUJ6ZEhsc1pUMGlabWxzYkRvalpUazJZalZrSWk4K1BDOW5QanhuSUhOMGVXeGxQU0pwYzI5c1lYUnBiMjQ2YVhOdmJHRjBaU0krUEhCaGRHZ2daRDBpVFRFek5TdzVNUzQ0TkdNd0xEVXVNVFl0TWk0eU5pdzNMalV6TFRrdU1qRXNOeTQxTXkwMkxqYzBMREF0T1M0ME15MHlMakk0TFRFeExqVTFMVGd1TmpORE1URXpMRGczTERFeE1pNDBOQ3czT1M0MU1pd3hNRGN1TlRJc056a3VOVEpvTFRFdU5sWTVPQzQyTldnMUxqSTRkaTR5T0VnNE9TNDNkaTB1TWpob05DNDRPVlkyTUM0M01VZzRPUzQzZGkwdU1qaElNVEE1WXpVdU5qWXNNQ3d4T0M0ME55NHlNaXd4T0M0ME55dzVMalEyTERBc055NDFOQzB4TUM0M055dzVMakkzTFRFM0xqTXlMRGt1TlRSMkxqQTVZekV3TGpjMUxEQXNNVE11T1RRc015NDFNaXd4Tmk0MU9DdzVMakUxTERNdU16TXNOeTR4TWl3MExqRXpMRGd1TVRjc05TNDFNeXc0TGpFM0xESXVNaXd3TERJdU5EY3RNeTR6TlN3eUxqUTNMVFZhYlMweU9TMHhNaTQyYURFdU5tTTFMalEwTERBc055NDRNUzB5TGpnMkxEY3VPREV0T1M0ek5Td3dMVFV1TVRFdE1TNDRNaTA1TGpFNExUY3VOemt0T1M0eE9HZ3RNUzQyTWxvaUlITjBlV3hsUFNKbWFXeHNPaU01WWpSaE9HUWlMejQ4TDJjK1BHY2djM1I1YkdVOUltbHpiMnhoZEdsdmJqcHBjMjlzWVhSbElqNDhjR0YwYUNCa1BTSk5NVGM0TGpZMUxEYzVMalk0WXpBc01USXVOVFF0T0M0NE5Td3hPUzQyT1MweE9TNDNNU3d4T1M0Mk9YTXRNVGt1TnpJdE55NHhOUzB4T1M0M01pMHhPUzQyT1ZNeE5EZ3VNRGNzTmpBc01UVTRMamswTERZd0xERTNPQzQyTlN3Mk55NHhOQ3d4TnpndU5qVXNOemt1TmpoYWJTMHhNUzQ0TERCak1DMDRMalF4TFM0MU1pMHhPUzQwTVMwM0xqa3hMVEU1TGpReFV6RTFNU3czTVM0eU55d3hOVEVzTnprdU5qaHpMalV5TERFNUxqUXhMRGN1T1RJc01Ua3VOREZUTVRZMkxqZzFMRGc0TGpFc01UWTJMamcxTERjNUxqWTRXaUlnYzNSNWJHVTlJbVpwYkd3NkkyVTVObUkxWkNJdlBqd3ZaejQ4WnlCemRIbHNaVDBpYVhOdmJHRjBhVzl1T21semIyeGhkR1VpUGp4d1lYUm9JR1E5SWsweU1qWXVOamdzTnprdU5qaGpNQ3d4TWk0MU5DMDRMamtzTVRrdU5qa3RNVGt1T0RNc01Ua3VOamxUTVRnM0xEa3lMakl5TERFNE55dzNPUzQyT0N3eE9UVXVPVElzTmpBc01qQTJMamcxTERZd0xESXlOaTQyT0N3Mk55NHhOQ3d5TWpZdU5qZ3NOemt1TmpoYWJTMHhNUzQ0Tnl3d1l6QXRPQzQwTVMwdU5USXRNVGt1TkRFdE9DMHhPUzQwTVhNdE9Dd3hNUzA0TERFNUxqUXhMalV5TERFNUxqUXhMRGdzTVRrdU5ERlRNakUwTGpneExEZzRMakVzTWpFMExqZ3hMRGM1TGpZNFdpSWdjM1I1YkdVOUltWnBiR3c2SXpsaU5HRTRaQ0l2UGp3dlp6NDhaeUJ6ZEhsc1pUMGlhWE52YkdGMGFXOXVPbWx6YjJ4aGRHVWlQanh3WVhSb0lHUTlJazB5TXpZdU5qa3NPVGd1T1ROMkxTNHlPR2cwTGpnNVZqWXdMamN4YUMwMExqZzVkaTB1TWpob016TXVPVE5NTWpjeUxEY3pMalk1YUMwdU1qZHNMUzR4TVMweFl5MHVPQzAzTGpVMkxUWXVPREl0TVRJdE1UUXVNeTB4TW1ndE5DNDBWamM1TGpFemFDNDJNV00yTGpFNExEQXNNVEF1TWkweUxqVTRMREV3TGpVdE55NDNNbXd1TURVdE1XZ3VNamhzTFM0NU15d3hOeTQzTjJndExqSTRiQzR3TlMweFl5NHlPQzAxTGpFeUxUTXVORGt0Tnk0NE1TMDVMalkzTFRjdU9ERm9MUzQyTVZZNU9DNDJOV2cxTGpnemRpNHlPRm9pSUhOMGVXeGxQU0ptYVd4c09pTTVZalJoT0dNaUx6NDhMMmMrUEdjZ2MzUjViR1U5SW1semIyeGhkR2x2YmpwcGMyOXNZWFJsSWo0OGNHRjBhQ0JrUFNKTk16QTNMamN4TERnM0xqTTRZekFzTnk0ME55MDJMamMxTERFMExqRTNMVEUwTGpjMkxERTBMakUzTFRZdU5ETXNNQzB4TUM0NE9TMDBMakkzTFRFd0xqZzVMVEV3TGpJeExEQXROeTQzTERZdU5qSXRNVFF1TVRnc01UUXVOekl0TVRRdU1UaERNekF6TGpJMkxEYzNMakUyTERNd055NDNNU3c0TVM0ME5Dd3pNRGN1TnpFc09EY3VNemhhYlMwNExqSXpMVFF1TmpSak1DMHlMalkxTFM0MUxUVXVNakl0TWk0M05TMDFMakl5TFRVc01DMDJMalF6TERFekxqZzJMVFl1TkRNc01UZ3VOVFFzTUN3eUxqWTJMalE1TERVdU1UTXNNaTQzTERVdU1UTkRNams0TERFd01TNHhPU3d5T1RrdU5EZ3NPRGd1TURVc01qazVMalE0TERneUxqYzBXaUlnYzNSNWJHVTlJbVpwYkd3Nkl6QmpZalpsWVNJdlBqd3ZaejQ4WnlCemRIbHNaVDBpYVhOdmJHRjBhVzl1T21semIyeGhkR1VpUGp4d1lYUm9JR1E5SWswek1EQXVNVE1zTVRBMUxqUTJZVFF1TmpFc05DNDJNU3d3TERBc01TdzBMalk0TFRRdU56Y3NNeTQ1TXl3ekxqa3pMREFzTUN3eExEUXVNRGtzTkM0eE9Dd3pMakkyTERNdU1qWXNNQ3d3TERBdE1pNDNMRE11TWpsak1Dd3hMakE0TGpRMUxERXVPVE1zTVM0M01Td3hMamt6TERJdU1USXNNQ3cwTFRJdU16UXNOQzAxTGpjMkxEQXRNaTR3TnkwdU5qY3ROQzR6TWkwMExUVXVORGxzTXk0ek55MHlNa2d6TURjdU5td3dMUzR6Tm1nekxqWTFZeTR6TVMwMkxqY3NNaTQxTWkweE1TNDRPQ3c1TGpFNExURXhMamc0TERRdU5Td3dMRFl1TlRjc01pNDBPQ3cyTGpVM0xEVXVNamRoTkM0M05TdzBMamMxTERBc01Dd3hMVFF1T0RJc05XTXRNaTR5TERBdE5DMHhMalEwTFRRdE5DNHlOMkV6TGpBNUxETXVNRGtzTUN3d0xEQXNNaTQ0T0MwekxqSmpNQzB4TGpNMUxTNDFPQzB5TGpJNUxUSXVNRGN0TWk0eU9TMDFMak14TERBdE5pNDROQ3d4TVM0ek9Dd3hMalEwTERFeExqTTRhRE11TW13d0xDNHpObWd0TkM0eU4wd3pNVFlzT1RndU56VmpMUzQ0Tml3MUxqUXRNeTQwTnl3eE1pMDVMamMzTERFeVF6TXdNaTR5T1N3eE1UQXVOeklzTXpBd0xqRXpMREV3T0M0eUxETXdNQzR4TXl3eE1EVXVORFphSWlCemRIbHNaVDBpWm1sc2JEb2pNR05pTm1WaElpOCtQQzluUGp4bklITjBlV3hsUFNKcGMyOXNZWFJwYjI0NmFYTnZiR0YwWlNJK1BIQmhkR2dnWkQwaVRUTTBOUzQ0TlN3NU9DNHhiQzAwTGpBM0xERXVNVFl0TGpnNExURTJhQzQwTkdNdU9EZ3NOaTQwTkN3MExqUTFMREUxTGpZeUxERTBMak0xTERFMUxqWXlMRFVzTUN3NUxURXVOellzT1MwMUxqZ3pMREF0T1M0eU5DMHlOQzA0TGpReExUSTBMVEl4TGpjeVF6TTBNQzQyT0N3Mk5Dd3pORGN1Tnpjc05qQXNNelUyTGpVM0xEWXdZVE01TGpNM0xETTVMak0zTERBc01Dd3hMRGd1TnpVc01TNHlObXcwTGpFNExURXVNVFl1TnpFc01UTXVOVE5vTFM0ME5HTXRMamc0TFRZdU1qRXROQzR6TkMweE15NHhPUzB4TXk0eUxURXpMakU1TFRRdU5Dd3dMVGN1TkRJc01pNHdPQzAzTGpReUxEVXVOallzTUN3NExqUXhMREkwTERjdU1Ea3NNalFzTWpBdU56a3NNQ3czTGpjMUxUZ3VNVE1zTVRJdU5EZ3RNVGN1TkRNc01USXVORGhCTkRFdU5qVXNOREV1TmpVc01Dd3dMREVzTXpRMUxqZzFMRGs0TGpGYUlpQnpkSGxzWlQwaVptbHNiRG9qTlRCaFpUVTRJaTgrUEhCaGRHZ2daRDBpVFRNNE5DNDJNaXc1T0M0NU0zWXRMalEwWXpVdU56SXNNQ3cyTGpJM0xUTXNOaTR5TnkwNUxqUTJWall3TGpnNFl5MDRMamt4TERBdE1USXVPRGNzTlM0ek15MHhNeTQ0TERFekxqWXphQzB1TkRSc01TNDBPQzB4TkM0d04wZzBNVFZzTVM0ME9Dd3hOQzR3TjBnME1UWmpMUzQ1TXkwNExqTXROQzQ0T1MweE15NDJNeTB4TXk0NExURXpMall6VmpnNVl6QXNOaTQwTkM0MU5TdzVMalEyTERZdU1qY3NPUzQwTm5ZdU5EUmFJaUJ6ZEhsc1pUMGlabWxzYkRvak5UQmhaVFU0SWk4K1BDOW5QanhuSUhOMGVXeGxQU0pwYzI5c1lYUnBiMjQ2YVhOdmJHRjBaU0krUEhCaGRHZ2daRDBpVFRRMU5TNDFOQ3c0T0M0ME0yTXpMalEyTERjdU1pdzFMakV4TERFd0xqQTJMRGt1TURjc01UQXVNRFoyTGpRMFNEUTBNaTR4T0hZdExqUTBZelV1TWpJc01DdzBMakU0TFRRdU1UZ3NNUzQwT0MwNUxqazFiQzB4TGpNNUxUTklOREk1TGpFNFl5MDBMRGd1TXpndE1pNDFPU3d4TWk0NU1pd3pMalF6TERFeUxqa3lkaTQwTkVnME1UY3VNWFl0TGpRMFl6UXNNQ3czTGpReUxUUXVOamNzTVRFdU56RXRNVE11TXpac01USXVOekV0TWpVdU56bGFUVFF5T1M0ME5TdzROVWcwTkRKc0xUWXVNVEV0TVRNdU1EaGFJaUJ6ZEhsc1pUMGlabWxzYkRvalpXWTRPVEUySWk4K1BIQmhkR2dnWkQwaVRUVXdOQzQzTVN3NE55NDJObU0wTGpJNUxEa3VOVEVzTlM0MUxERXdMak01TERndU1UUXNNVEF1TVRGMkxqUTFZVE0yTGprMExETTJMamswTERBc01Dd3hMVGd1TnpVc01TNHlObU10Tmk0M05pd3dMVGt1TkMweUxqVTRMVEV4TGpRekxUZ3VOelF0TVM0M05pMDFMak0wTFRNdU1qVXRNVEV1TkRRdE5pNDNOeTB4TVM0ME5HRTBMakEzTERRdU1EY3NNQ3d3TERBdE1TNDRNUzQwTmxZNE9XTXdMRFl1TkRRdU5Ea3NPUzQwTml3MExqVTJMRGt1TkRaMkxqUTBTRFEyTnk0eU5uWXRMalEwWXpVdU5Td3dMRFV1TlMwekxEVXVOUzA1TGpRMlZqY3dMak16WXpBdE5pNDJOU3d3TFRrdU5EWXROUzQxTFRrdU5EWjJMUzQwTTJneU1TNHpPWFl1TkROakxUUXVNRGNzTUMwMExqVTJMRE10TkM0MU5pdzVMalEyVmpjNUxqRnNOeTAzTGpZM1l6SXVNell0TWk0MU15dzFMak01TFRZdU1UWXNOUzR6T1MwNExqUXhMREF0TVM0ME9TMHhMVEl1TVRVdE15NDJNeTB5TGpFMWRpMHVORE5vTVRZdU5qWjJMalF6WXkwM0xEQXRNVFF1Tmpnc055NHpNaTB4T0N3eE1DNDVOV3d0Tmk0ME9DdzNZVEU0TERFNExEQXNNQ3d4TERndU1qUXRNbU0xTGpVMkxEQXNPQzR4T1N3ekxqTXNNVEV1TkRRc01UQXVPRFJhSWlCemRIbHNaVDBpWm1sc2JEb2paV1k0T1RFMklpOCtQQzluUGp4bklITjBlV3hsUFNKcGMyOXNZWFJwYjI0NmFYTnZiR0YwWlNJK1BIQmhkR2dnWkQwaVRUVTFNaTR5TERjekxqWTVhQzB1TWpoc0xTNHhNUzB4WXkwdU9DMDNMalUyTFRZdU9ESXRNVEl0TVRRdU15MHhNa2cxTXpKV056a3VNVE5vTGpZeFl6WXVNVGdzTUN3eE1DNHlMVEl1TlRnc01UQXVOUzAzTGpjeWJDNHdOaTB4YUM0eU4yd3RMamt6TERFM0xqYzNhQzB1TWpoc0xqQTJMVEZqTGpJM0xUVXVNVEl0TXk0MUxUY3VPREV0T1M0Mk9DMDNMamd4U0RVek1sWTVNbU13TERVdU16TXVOakVzTmk0M0xEUXVOQ3cyTGpjc09TNDROeXd3TERFMkxUWXVNVFVzTVRjdU16VXRNVFZzTGpJdE1TNHlOR2d1TWpkc0xUSXVOalFzTVRZdU5XZ3RNelV1T0hZdExqSTRhRFF1T0RsV05qQXVOekZvTFRRdU9EbDJMUzR5TjJnek5Wb2lJSE4wZVd4bFBTSm1hV3hzT2lNMU1HRmxOVGdpTHo0OEwyYytQSFJsZUhRZ1kyeGhjM005SW13aUlIUnlZVzV6Wm05eWJUMGlkSEpoYm5Oc1lYUmxLREl6TlM0eE5TQXlOalVwSWo1MmFYUmhiR2xyTG1WMGFEd3ZkR1Y0ZEQ0Z1BIUmxlSFFnWTJ4aGMzTTlJbTBpSUhSeVlXNXpabTl5YlQwaWRISmhibk5zWVhSbEtESTJNeTQwT0NBeU9UVXBJajV6YVdkdVpYSThMM1JsZUhRK0lEeDBaWGgwSUdOc1lYTnpQU0p0SWlCMGNtRnVjMlp2Y20wOUluUnlZVzV6YkdGMFpTZ3lORFV1TmpRZ016Y3pLU0krY21WamFYQnBaVzUwUEM5MFpYaDBQand2YzNablBnPT0ifQ==\n")])])]),M("p",[T._v("在使用 base64 格式解碼後可以得到以下資料:")]),T._v(" "),M("div",{staticClass:"language-json extra-class"},[M("pre",{pre:!0,attrs:{class:"language-json"}},[M("code",[M("span",{pre:!0,attrs:{class:"token punctuation"}},[T._v("{")]),T._v("\n "),M("span",{pre:!0,attrs:{class:"token property"}},[T._v('"signed_to"')]),M("span",{pre:!0,attrs:{class:"token operator"}},[T._v(":")]),M("span",{pre:!0,attrs:{class:"token string"}},[T._v('"hydai.eth"')]),M("span",{pre:!0,attrs:{class:"token punctuation"}},[T._v(",")]),T._v("\n "),M("span",{pre:!0,attrs:{class:"token property"}},[T._v('"external_url"')]),M("span",{pre:!0,attrs:{class:"token operator"}},[T._v(":")]),M("span",{pre:!0,attrs:{class:"token string"}},[T._v('"https://proofofstake.gitcoin.co/"')]),M("span",{pre:!0,attrs:{class:"token punctuation"}},[T._v(",")]),T._v("\n "),M("span",{pre:!0,attrs:{class:"token property"}},[T._v('"timestamp"')]),M("span",{pre:!0,attrs:{class:"token operator"}},[T._v(":")]),M("span",{pre:!0,attrs:{class:"token string"}},[T._v('"1662830690"')]),M("span",{pre:!0,attrs:{class:"token punctuation"}},[T._v(",")]),T._v("\n "),M("span",{pre:!0,attrs:{class:"token property"}},[T._v('"pledge"')]),M("span",{pre:!0,attrs:{class:"token operator"}},[T._v(":")]),M("span",{pre:!0,attrs:{class:"token string"}},[T._v('"50000000000000000"')]),M("span",{pre:!0,attrs:{class:"token punctuation"}},[T._v(",")]),T._v("\n "),M("span",{pre:!0,attrs:{class:"token property"}},[T._v('"message"')]),M("span",{pre:!0,attrs:{class:"token operator"}},[T._v(":")]),M("span",{pre:!0,attrs:{class:"token string"}},[T._v('"Thank you for supporting public goods, and enjoy the book!"')]),M("span",{pre:!0,attrs:{class:"token punctuation"}},[T._v(",")]),T._v("\n "),M("span",{pre:!0,attrs:{class:"token property"}},[T._v('"image"')]),M("span",{pre:!0,attrs:{class:"token operator"}},[T._v(":")]),M("span",{pre:!0,attrs:{class:"token string"}},[T._v('"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MDYuMiIgaGVpZ2h0PSI4MTkuNCIgdmlld0JveD0iMCAwIDYwNi4yIDgxOS40Ij48ZGVmcz48c3R5bGU+LmF7ZmlsbDojZmZmO30uYntmaWxsOm5vbmU7c3Ryb2tlOiNkOWM4ZGI7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLXdpZHRoOjJweDt9LmMsLmQsLmUsLmYsLmcsLmgsLmksLmosLmssLmwsLm0sLm4sLm97aXNvbGF0aW9uOmlzb2xhdGU7fS5jLC5kLC5lLC5mLC5nLC5pLC5qLC5re2ZvbnQtc2l6ZTo1NXB4O30uYywuZXtmaWxsOiNlOTZiNWQ7fS5jLC5kLC5lLC5mLC5nLC5re2ZvbnQtZmFtaWx5Okx1c3REaXNwbGF5LURpZG9uZSwgTHVzdCBEaWRvbmU7fS5kLC5me2ZpbGw6IzliNGE4ZDt9LmV7bGV0dGVyLXNwYWNpbmc6MC4wMmVtO30uZntsZXR0ZXItc3BhY2luZzowLjAyZW07fS5ne2ZpbGw6IzliNGE4Yzt9Lmh7Zm9udC1zaXplOjQ1cHg7ZmlsbDojMGNiNmVhO2ZvbnQtZmFtaWx5Okx1c3QtSXRhbGljLCBMdXN0O2ZvbnQtc3R5bGU6aXRhbGljO30uaSwua3tmaWxsOiM1MGFlNTg7fS5pLC5qe2ZvbnQtZmFtaWx5Okx1c3QtUmVndWxhciwgTHVzdDtsZXR0ZXItc3BhY2luZzowLjA1ZW07fS5qe2ZpbGw6I2VmODkxNjt9LmwsLm17Zm9udC1zaXplOjI5Ljk5cHg7fS5sLC5ue2ZvbnQtZmFtaWx5OkFyaWFsLUJvbGRNVCwgQXJpYWw7Zm9udC13ZWlnaHQ6NzAwO30ubSwub3tmb250LWZhbWlseTpBcmlhbE1ULCBBcmlhbDsgbWFyZ2luLWxlZnQ6IGF1dG87IG1hcmdpbi1yaWdodDogYXV0bzsgd2lkdGg6IDQwJTt9Lm57Zm9udC1zaXplOjIwcHg7fS5ve2ZvbnQtc2l6ZToxOHB4O308L3N0eWxlPjwvZGVmcz48cmVjdCBjbGFzcz0iYSIgd2lkdGg9IjYwNi4yIiBoZWlnaHQ9IjgxOS40Ii8+PHRleHQgY2xhc3M9Im4iPjx0c3BhbiBjbGFzcz0ibiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNTAlIiB5PSI0MiUiPmh5ZGFpLmV0aDwvdHNwYW4+PC90ZXh0Pjx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDc1IDM1Mi44NSkiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtZmFtaWx5PSJBcmlhbE1ULCBBcmlhbCI+PHRzcGFuIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3LjUlIiB5PSIyMDAiPjE2NjI4MzA2OTA8L3RzcGFuPjx0c3BhbiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzNy41JSIgeT0iMjYwIj41MDAwMDAwMDAwMDAwMDAwMCAod2VpKTwvdHNwYW4+PHRzcGFuIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3LjUlIiB5PSIzMjAiPjB4NWJmNWJjYzUzNjJmODg3MjExNjdjMTA2OGI1OGM2MGNhZDA3NWFhYzwvdHNwYW4+PHRzcGFuIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3LjUlIiB5PSIxMjAiPiJUaGFuayB5b3UgZm9yIHN1cHBvcnRpbmcgcHVibGljIGdvb2RzLCBhbmQgZW5qb3kgdGhlIGJvb2shIjwvdHNwYW4+PHRzcGFuIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3LjUlIiB5PSIyMjAiPm1pbnQgdGltZXN0YW1wPC90c3Bhbj48dHNwYW4gdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzcuNSUiIHk9IjM0MCI+Y29udHJhY3Q8L3RzcGFuPjx0c3BhbiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzNy41JSIgeT0iMjgwIj52YWx1ZTwvdHNwYW4+PHRzcGFuIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3LjUlIiB5PSIxNDAiPjwvdHNwYW4+PC90ZXh0PjxyZWN0IGNsYXNzPSJiIiB4PSIyMS45IiB5PSIxNjkuNSIgd2lkdGg9IjU2Mi40IiBoZWlnaHQ9IjU2Mi40Ii8+PGcgc3R5bGU9Imlzb2xhdGlvbjppc29sYXRlIj48cGF0aCBkPSJNNDYuNjYsOTguOTN2LS4yOGg0Ljg5VjYwLjcxSDQ2LjY2di0uMjhINjUuOTFjMTIsMCwxOC40MiwzLjE5LDE4LjQyLDExLjE3LDAsOS40LTExLjc3LDExLjI3LTE5Ljg1LDExLjI3aC0xLjZWOTguNjVoNS44M3YuMjhaTTYyLjg4LDgyLjZoMS42YzUuODMsMCw3Ljc1LTMuNDcsNy43NS0xMXMtMS45Mi0xMC44OS03Ljc1LTEwLjg5aC0xLjZaIiBzdHlsZT0iZmlsbDojZTk2YjVkIi8+PC9nPjxnIHN0eWxlPSJpc29sYXRpb246aXNvbGF0ZSI+PHBhdGggZD0iTTEzNSw5MS44NGMwLDUuMTYtMi4yNiw3LjUzLTkuMjEsNy41My02Ljc0LDAtOS40My0yLjI4LTExLjU1LTguNjNDMTEzLDg3LDExMi40NCw3OS41MiwxMDcuNTIsNzkuNTJoLTEuNlY5OC42NWg1LjI4di4yOEg4OS43di0uMjhoNC44OVY2MC43MUg4OS43di0uMjhIMTA5YzUuNjYsMCwxOC40Ny4yMiwxOC40Nyw5LjQ2LDAsNy41NC0xMC43Nyw5LjI3LTE3LjMyLDkuNTR2LjA5YzEwLjc1LDAsMTMuOTQsMy41MiwxNi41OCw5LjE1LDMuMzMsNy4xMiw0LjEzLDguMTcsNS41Myw4LjE3LDIuMiwwLDIuNDctMy4zNSwyLjQ3LTVabS0yOS0xMi42aDEuNmM1LjQ0LDAsNy44MS0yLjg2LDcuODEtOS4zNSwwLTUuMTEtMS44Mi05LjE4LTcuNzktOS4xOGgtMS42MloiIHN0eWxlPSJmaWxsOiM5YjRhOGQiLz48L2c+PGcgc3R5bGU9Imlzb2xhdGlvbjppc29sYXRlIj48cGF0aCBkPSJNMTc4LjY1LDc5LjY4YzAsMTIuNTQtOC44NSwxOS42OS0xOS43MSwxOS42OXMtMTkuNzItNy4xNS0xOS43Mi0xOS42OVMxNDguMDcsNjAsMTU4Ljk0LDYwLDE3OC42NSw2Ny4xNCwxNzguNjUsNzkuNjhabS0xMS44LDBjMC04LjQxLS41Mi0xOS40MS03LjkxLTE5LjQxUzE1MSw3MS4yNywxNTEsNzkuNjhzLjUyLDE5LjQxLDcuOTIsMTkuNDFTMTY2Ljg1LDg4LjEsMTY2Ljg1LDc5LjY4WiIgc3R5bGU9ImZpbGw6I2U5NmI1ZCIvPjwvZz48ZyBzdHlsZT0iaXNvbGF0aW9uOmlzb2xhdGUiPjxwYXRoIGQ9Ik0yMjYuNjgsNzkuNjhjMCwxMi41NC04LjksMTkuNjktMTkuODMsMTkuNjlTMTg3LDkyLjIyLDE4Nyw3OS42OCwxOTUuOTIsNjAsMjA2Ljg1LDYwLDIyNi42OCw2Ny4xNCwyMjYuNjgsNzkuNjhabS0xMS44NywwYzAtOC40MS0uNTItMTkuNDEtOC0xOS40MXMtOCwxMS04LDE5LjQxLjUyLDE5LjQxLDgsMTkuNDFTMjE0LjgxLDg4LjEsMjE0LjgxLDc5LjY4WiIgc3R5bGU9ImZpbGw6IzliNGE4ZCIvPjwvZz48ZyBzdHlsZT0iaXNvbGF0aW9uOmlzb2xhdGUiPjxwYXRoIGQ9Ik0yMzYuNjksOTguOTN2LS4yOGg0Ljg5VjYwLjcxaC00Ljg5di0uMjhoMzMuOTNMMjcyLDczLjY5aC0uMjdsLS4xMS0xYy0uOC03LjU2LTYuODItMTItMTQuMy0xMmgtNC40Vjc5LjEzaC42MWM2LjE4LDAsMTAuMi0yLjU4LDEwLjUtNy43MmwuMDUtMWguMjhsLS45MywxNy43N2gtLjI4bC4wNS0xYy4yOC01LjEyLTMuNDktNy44MS05LjY3LTcuODFoLS42MVY5OC42NWg1Ljgzdi4yOFoiIHN0eWxlPSJmaWxsOiM5YjRhOGMiLz48L2c+PGcgc3R5bGU9Imlzb2xhdGlvbjppc29sYXRlIj48cGF0aCBkPSJNMzA3LjcxLDg3LjM4YzAsNy40Ny02Ljc1LDE0LjE3LTE0Ljc2LDE0LjE3LTYuNDMsMC0xMC44OS00LjI3LTEwLjg5LTEwLjIxLDAtNy43LDYuNjItMTQuMTgsMTQuNzItMTQuMThDMzAzLjI2LDc3LjE2LDMwNy43MSw4MS40NCwzMDcuNzEsODcuMzhabS04LjIzLTQuNjRjMC0yLjY1LS41LTUuMjItMi43NS01LjIyLTUsMC02LjQzLDEzLjg2LTYuNDMsMTguNTQsMCwyLjY2LjQ5LDUuMTMsMi43LDUuMTNDMjk4LDEwMS4xOSwyOTkuNDgsODguMDUsMjk5LjQ4LDgyLjc0WiIgc3R5bGU9ImZpbGw6IzBjYjZlYSIvPjwvZz48ZyBzdHlsZT0iaXNvbGF0aW9uOmlzb2xhdGUiPjxwYXRoIGQ9Ik0zMDAuMTMsMTA1LjQ2YTQuNjEsNC42MSwwLDAsMSw0LjY4LTQuNzcsMy45MywzLjkzLDAsMCwxLDQuMDksNC4xOCwzLjI2LDMuMjYsMCwwLDAtMi43LDMuMjljMCwxLjA4LjQ1LDEuOTMsMS43MSwxLjkzLDIuMTIsMCw0LTIuMzQsNC01Ljc2LDAtMi4wNy0uNjctNC4zMi00LTUuNDlsMy4zNy0yMkgzMDcuNmwwLS4zNmgzLjY1Yy4zMS02LjcsMi41Mi0xMS44OCw5LjE4LTExLjg4LDQuNSwwLDYuNTcsMi40OCw2LjU3LDUuMjdhNC43NSw0Ljc1LDAsMCwxLTQuODIsNWMtMi4yLDAtNC0xLjQ0LTQtNC4yN2EzLjA5LDMuMDksMCwwLDAsMi44OC0zLjJjMC0xLjM1LS41OC0yLjI5LTIuMDctMi4yOS01LjMxLDAtNi44NCwxMS4zOCwxLjQ0LDExLjM4aDMuMmwwLC4zNmgtNC4yN0wzMTYsOTguNzVjLS44Niw1LjQtMy40NywxMi05Ljc3LDEyQzMwMi4yOSwxMTAuNzIsMzAwLjEzLDEwOC4yLDMwMC4xMywxMDUuNDZaIiBzdHlsZT0iZmlsbDojMGNiNmVhIi8+PC9nPjxnIHN0eWxlPSJpc29sYXRpb246aXNvbGF0ZSI+PHBhdGggZD0iTTM0NS44NSw5OC4xbC00LjA3LDEuMTYtLjg4LTE2aC40NGMuODgsNi40NCw0LjQ1LDE1LjYyLDE0LjM1LDE1LjYyLDUsMCw5LTEuNzYsOS01LjgzLDAtOS4yNC0yNC04LjQxLTI0LTIxLjcyQzM0MC42OCw2NCwzNDcuNzcsNjAsMzU2LjU3LDYwYTM5LjM3LDM5LjM3LDAsMCwxLDguNzUsMS4yNmw0LjE4LTEuMTYuNzEsMTMuNTNoLS40NGMtLjg4LTYuMjEtNC4zNC0xMy4xOS0xMy4yLTEzLjE5LTQuNCwwLTcuNDIsMi4wOC03LjQyLDUuNjYsMCw4LjQxLDI0LDcuMDksMjQsMjAuNzksMCw3Ljc1LTguMTMsMTIuNDgtMTcuNDMsMTIuNDhBNDEuNjUsNDEuNjUsMCwwLDEsMzQ1Ljg1LDk4LjFaIiBzdHlsZT0iZmlsbDojNTBhZTU4Ii8+PHBhdGggZD0iTTM4NC42Miw5OC45M3YtLjQ0YzUuNzIsMCw2LjI3LTMsNi4yNy05LjQ2VjYwLjg4Yy04LjkxLDAtMTIuODcsNS4zMy0xMy44LDEzLjYzaC0uNDRsMS40OC0xNC4wN0g0MTVsMS40OCwxNC4wN0g0MTZjLS45My04LjMtNC44OS0xMy42My0xMy44LTEzLjYzVjg5YzAsNi40NC41NSw5LjQ2LDYuMjcsOS40NnYuNDRaIiBzdHlsZT0iZmlsbDojNTBhZTU4Ii8+PC9nPjxnIHN0eWxlPSJpc29sYXRpb246aXNvbGF0ZSI+PHBhdGggZD0iTTQ1NS41NCw4OC40M2MzLjQ2LDcuMiw1LjExLDEwLjA2LDkuMDcsMTAuMDZ2LjQ0SDQ0Mi4xOHYtLjQ0YzUuMjIsMCw0LjE4LTQuMTgsMS40OC05Ljk1bC0xLjM5LTNINDI5LjE4Yy00LDguMzgtMi41OSwxMi45MiwzLjQzLDEyLjkydi40NEg0MTcuMXYtLjQ0YzQsMCw3LjQyLTQuNjcsMTEuNzEtMTMuMzZsMTIuNzEtMjUuNzlaTTQyOS40NSw4NUg0NDJsLTYuMTEtMTMuMDhaIiBzdHlsZT0iZmlsbDojZWY4OTE2Ii8+PHBhdGggZD0iTTUwNC43MSw4Ny42NmM0LjI5LDkuNTEsNS41LDEwLjM5LDguMTQsMTAuMTF2LjQ1YTM2Ljk0LDM2Ljk0LDAsMCwxLTguNzUsMS4yNmMtNi43NiwwLTkuNC0yLjU4LTExLjQzLTguNzQtMS43Ni01LjM0LTMuMjUtMTEuNDQtNi43Ny0xMS40NGE0LjA3LDQuMDcsMCwwLDAtMS44MS40NlY4OWMwLDYuNDQuNDksOS40Niw0LjU2LDkuNDZ2LjQ0SDQ2Ny4yNnYtLjQ0YzUuNSwwLDUuNS0zLDUuNS05LjQ2VjcwLjMzYzAtNi42NSwwLTkuNDYtNS41LTkuNDZ2LS40M2gyMS4zOXYuNDNjLTQuMDcsMC00LjU2LDMtNC41Niw5LjQ2Vjc5LjFsNy03LjY3YzIuMzYtMi41Myw1LjM5LTYuMTYsNS4zOS04LjQxLDAtMS40OS0xLTIuMTUtMy42My0yLjE1di0uNDNoMTYuNjZ2LjQzYy03LDAtMTQuNjgsNy4zMi0xOCwxMC45NWwtNi40OCw3YTE4LDE4LDAsMCwxLDguMjQtMmM1LjU2LDAsOC4xOSwzLjMsMTEuNDQsMTAuODRaIiBzdHlsZT0iZmlsbDojZWY4OTE2Ii8+PC9nPjxnIHN0eWxlPSJpc29sYXRpb246aXNvbGF0ZSI+PHBhdGggZD0iTTU1Mi4yLDczLjY5aC0uMjhsLS4xMS0xYy0uOC03LjU2LTYuODItMTItMTQuMy0xMkg1MzJWNzkuMTNoLjYxYzYuMTgsMCwxMC4yLTIuNTgsMTAuNS03LjcybC4wNi0xaC4yN2wtLjkzLDE3Ljc3aC0uMjhsLjA2LTFjLjI3LTUuMTItMy41LTcuODEtOS42OC03LjgxSDUzMlY5MmMwLDUuMzMuNjEsNi43LDQuNCw2LjcsOS44NywwLDE2LTYuMTUsMTcuMzUtMTVsLjItMS4yNGguMjdsLTIuNjQsMTYuNWgtMzUuOHYtLjI4aDQuODlWNjAuNzFoLTQuODl2LS4yN2gzNVoiIHN0eWxlPSJmaWxsOiM1MGFlNTgiLz48L2c+PHRleHQgY2xhc3M9ImwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIzNS4xNSAyNjUpIj52aXRhbGlrLmV0aDwvdGV4dD4gPHRleHQgY2xhc3M9Im0iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI2My40OCAyOTUpIj5zaWduZXI8L3RleHQ+IDx0ZXh0IGNsYXNzPSJtIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNDUuNjQgMzczKSI+cmVjaXBpZW50PC90ZXh0Pjwvc3ZnPg=="')]),T._v("\n"),M("span",{pre:!0,attrs:{class:"token punctuation"}},[T._v("}")]),T._v("\n")])])]),M("h2",{attrs:{id:"結語"}},[M("a",{staticClass:"header-anchor",attrs:{href:"#結語"}},[T._v("#")]),T._v(" 結語")]),T._v(" "),M("p",[T._v("通過 URI JSON Schema 我們可以把 NFT 的詳細資訊給記錄在合約中。然而,Proof-of-Stake: Pages 的圖片非常簡單,因此可以使用 SVG 圖片格式直接編碼在 URI 內。")]),T._v(" "),M("p",[T._v("但,如果 NFT 代表的是一部 4K 影片、一張 8K 圖片等大型檔案,由於儲存成本會變得過高,因此會改用連結到該檔案的方式取代。")])])}),[],!1,null,null,null);M.default=U.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[38],{359:function(T,M,N){"use strict";N.r(M);var a=N(17),U=Object(a.a)({},(function(){var T=this,M=T._self._c;return M("ContentSlotsDistributor",{attrs:{"slot-key":T.$parent.slotKey}},[M("h1",{attrs:{id:"erc721-的元資料擴充-metadata-extension"}},[M("a",{staticClass:"header-anchor",attrs:{href:"#erc721-的元資料擴充-metadata-extension"}},[T._v("#")]),T._v(" ERC721 的元資料擴充(metadata extension)")]),T._v(" "),M("p",[T._v("一個 ERC721 的標準中,我們可以發現它定義了每個 NFT 對應到獨一無二的 "),M("code",[T._v("tokenId")]),T._v(",但卻沒有把每個 NFT 的實際資料儲存在合約中,這樣我們怎麼知道花了大錢買的 NFT 就是一張 JPG 圖片呢?")]),T._v(" "),M("h2",{attrs:{id:"erc721-metadata-extension"}},[M("a",{staticClass:"header-anchor",attrs:{href:"#erc721-metadata-extension"}},[T._v("#")]),T._v(" ERC721 metadata extension")]),T._v(" "),M("div",{staticClass:"language- extra-class"},[M("pre",{pre:!0,attrs:{class:"language-text"}},[M("code",[T._v("interface ERC721Metadata /* is ERC721 */ {\n /// 回傳本 NFT 系列的名稱\n function name() external view returns (string _name);\n\n /// 回傳本 NFT 系列的簡稱\n function symbol() external view returns (string _symbol);\n\n /// 回傳 URI (Uniform Resource Identifier)\n /// URI 可能指向一個代表了 ERC721 元資料 JSON 綱要的檔案\n function tokenURI(uint256 _tokenId) external view returns (string);\n}\n")])])]),M("h3",{attrs:{id:"erc721-metadata-json-schema"}},[M("a",{staticClass:"header-anchor",attrs:{href:"#erc721-metadata-json-schema"}},[T._v("#")]),T._v(" ERC721 metadata JSON schema")]),T._v(" "),M("p",[T._v("就是一個簡單的 JSON 格式,紀錄了 NFT 的名稱、簡介、與圖片。")]),T._v(" "),M("div",{staticClass:"language- extra-class"},[M("pre",{pre:!0,attrs:{class:"language-text"}},[M("code",[T._v('{\n "title": "Asset Metadata",\n "type": "object",\n "properties": {\n "name": {\n "type": "string",\n "description": "Identifies the asset to which this NFT represents"\n },\n "description": {\n "type": "string",\n "description": "Describes the asset to which this NFT represents"\n },\n "image": {\n "type": "string",\n "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive."\n }\n }\n}\n')])])]),M("h2",{attrs:{id:"以-proof-of-stake-pages-為例"}},[M("a",{staticClass:"header-anchor",attrs:{href:"#以-proof-of-stake-pages-為例"}},[T._v("#")]),T._v(" 以 Proof of Stake: Pages 為例")]),T._v(" "),M("p",[T._v("OpenSea 頁面: https://opensea.io/collection/proof-of-stake-pages\n在 etherscan 上的頁面: https://etherscan.io/address/0x5bf5bcc5362f88721167c1068b58c60cad075aac")]),T._v(" "),M("p",[T._v("這是一本由 Vitalik 寫的書,價格是自由樂捐的,他會以 NFT 的形式紀錄了捐款的證書。")]),T._v(" "),M("h3",{attrs:{id:"nft-圖片"}},[M("a",{staticClass:"header-anchor",attrs:{href:"#nft-圖片"}},[T._v("#")]),T._v(" NFT 圖片")]),T._v(" "),M("p",[T._v("比如,這就是我捐款的證明:\n"),M("img",{attrs:{src:"https://i.imgur.com/daplCPL.png",alt:""}})]),T._v(" "),M("h3",{attrs:{id:"nft-uri"}},[M("a",{staticClass:"header-anchor",attrs:{href:"#nft-uri"}},[T._v("#")]),T._v(" NFT URI")]),T._v(" "),M("p",[T._v("而我的 "),M("code",[T._v("tokenId")]),T._v(" 為 "),M("code",[T._v("59383")]),T._v(",我們可以去 etherscan 上面用 ERC721 的介面來查詢 URI 的資訊:")]),T._v(" "),M("p",[M("img",{attrs:{src:"https://i.imgur.com/C10im3R.jpg",alt:""}})]),T._v(" "),M("p",[T._v("此時可以看到他是以 JSON base64 編碼的方式儲存在上面:")]),T._v(" "),M("div",{staticClass:"language- extra-class"},[M("pre",{pre:!0,attrs:{class:"language-text"}},[M("code",[T._v("eyJzaWduZWRfdG8iOiJoeWRhaS5ldGgiLCAiZXh0ZXJuYWxfdXJsIjoiaHR0cHM6Ly9wcm9vZm9mc3Rha2UuZ2l0Y29pbi5jby8iLCAidGltZXN0YW1wIjoiMTY2MjgzMDY5MCIsICJwbGVkZ2UiOiI1MDAwMDAwMDAwMDAwMDAwMCIsICJtZXNzYWdlIjoiVGhhbmsgeW91IGZvciBzdXBwb3J0aW5nIHB1YmxpYyBnb29kcywgYW5kIGVuam95IHRoZSBib29rISIsICJpbWFnZSI6ICJkYXRhOmltYWdlL3N2Zyt4bWw7YmFzZTY0LFBITjJaeUI0Yld4dWN6MGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNakF3TUM5emRtY2lJSGRwWkhSb1BTSTJNRFl1TWlJZ2FHVnBaMmgwUFNJNE1Ua3VOQ0lnZG1sbGQwSnZlRDBpTUNBd0lEWXdOaTR5SURneE9TNDBJajQ4WkdWbWN6NDhjM1I1YkdVK0xtRjdabWxzYkRvalptWm1PMzB1WW50bWFXeHNPbTV2Ym1VN2MzUnliMnRsT2lOa09XTTRaR0k3YzNSeWIydGxMVzFwZEdWeWJHbHRhWFE2TVRBN2MzUnliMnRsTFhkcFpIUm9Pakp3ZUR0OUxtTXNMbVFzTG1Vc0xtWXNMbWNzTG1nc0xta3NMbW9zTG1zc0xtd3NMbTBzTG00c0xtOTdhWE52YkdGMGFXOXVPbWx6YjJ4aGRHVTdmUzVqTEM1a0xDNWxMQzVtTEM1bkxDNXBMQzVxTEM1cmUyWnZiblF0YzJsNlpUbzFOWEI0TzMwdVl5d3VaWHRtYVd4c09pTmxPVFppTldRN2ZTNWpMQzVrTEM1bExDNW1MQzVuTEM1cmUyWnZiblF0Wm1GdGFXeDVPa3gxYzNSRWFYTndiR0Y1TFVScFpHOXVaU3dnVEhWemRDQkVhV1J2Ym1VN2ZTNWtMQzVtZTJacGJHdzZJemxpTkdFNFpEdDlMbVY3YkdWMGRHVnlMWE53WVdOcGJtYzZNQzR3TW1WdE8zMHVabnRzWlhSMFpYSXRjM0JoWTJsdVp6b3dMakF5WlcwN2ZTNW5lMlpwYkd3Nkl6bGlOR0U0WXp0OUxtaDdabTl1ZEMxemFYcGxPalExY0hnN1ptbHNiRG9qTUdOaU5tVmhPMlp2Ym5RdFptRnRhV3g1T2t4MWMzUXRTWFJoYkdsakxDQk1kWE4wTzJadmJuUXRjM1I1YkdVNmFYUmhiR2xqTzMwdWFTd3VhM3RtYVd4c09pTTFNR0ZsTlRnN2ZTNXBMQzVxZTJadmJuUXRabUZ0YVd4NU9reDFjM1F0VW1WbmRXeGhjaXdnVEhWemREdHNaWFIwWlhJdGMzQmhZMmx1Wnpvd0xqQTFaVzA3ZlM1cWUyWnBiR3c2STJWbU9Ea3hOanQ5TG13c0xtMTdabTl1ZEMxemFYcGxPakk1TGprNWNIZzdmUzVzTEM1dWUyWnZiblF0Wm1GdGFXeDVPa0Z5YVdGc0xVSnZiR1JOVkN3Z1FYSnBZV3c3Wm05dWRDMTNaV2xuYUhRNk56QXdPMzB1YlN3dWIzdG1iMjUwTFdaaGJXbHNlVHBCY21saGJFMVVMQ0JCY21saGJEc2diV0Z5WjJsdUxXeGxablE2SUdGMWRHODdJRzFoY21kcGJpMXlhV2RvZERvZ1lYVjBienNnZDJsa2RHZzZJRFF3SlR0OUxtNTdabTl1ZEMxemFYcGxPakl3Y0hnN2ZTNXZlMlp2Ym5RdGMybDZaVG94T0hCNE8zMDhMM04wZVd4bFBqd3ZaR1ZtY3o0OGNtVmpkQ0JqYkdGemN6MGlZU0lnZDJsa2RHZzlJall3Tmk0eUlpQm9aV2xuYUhROUlqZ3hPUzQwSWk4K1BIUmxlSFFnWTJ4aGMzTTlJbTRpUGp4MGMzQmhiaUJqYkdGemN6MGliaUlnZEdWNGRDMWhibU5vYjNJOUltMXBaR1JzWlNJZ2VEMGlOVEFsSWlCNVBTSTBNaVVpUG1oNVpHRnBMbVYwYUR3dmRITndZVzQrUEM5MFpYaDBQangwWlhoMElIUnlZVzV6Wm05eWJUMGlkSEpoYm5Oc1lYUmxLRGMxSURNMU1pNDROU2tpSUdadmJuUXRjMmw2WlQwaU1UZ2lJR1p2Ym5RdFptRnRhV3g1UFNKQmNtbGhiRTFVTENCQmNtbGhiQ0krUEhSemNHRnVJSFJsZUhRdFlXNWphRzl5UFNKdGFXUmtiR1VpSUhnOUlqTTNMalVsSWlCNVBTSXlNREFpUGpFMk5qSTRNekEyT1RBOEwzUnpjR0Z1UGp4MGMzQmhiaUIwWlhoMExXRnVZMmh2Y2owaWJXbGtaR3hsSWlCNFBTSXpOeTQxSlNJZ2VUMGlNall3SWo0MU1EQXdNREF3TURBd01EQXdNREF3TUNBb2QyVnBLVHd2ZEhOd1lXNCtQSFJ6Y0dGdUlIUmxlSFF0WVc1amFHOXlQU0p0YVdSa2JHVWlJSGc5SWpNM0xqVWxJaUI1UFNJek1qQWlQakI0TldKbU5XSmpZelV6TmpKbU9EZzNNakV4Tmpkak1UQTJPR0kxT0dNMk1HTmhaREEzTldGaFl6d3ZkSE53WVc0K1BIUnpjR0Z1SUhSbGVIUXRZVzVqYUc5eVBTSnRhV1JrYkdVaUlIZzlJak0zTGpVbElpQjVQU0l4TWpBaVBpSlVhR0Z1YXlCNWIzVWdabTl5SUhOMWNIQnZjblJwYm1jZ2NIVmliR2xqSUdkdmIyUnpMQ0JoYm1RZ1pXNXFiM2tnZEdobElHSnZiMnNoSWp3dmRITndZVzQrUEhSemNHRnVJSFJsZUhRdFlXNWphRzl5UFNKdGFXUmtiR1VpSUhnOUlqTTNMalVsSWlCNVBTSXlNakFpUG0xcGJuUWdkR2x0WlhOMFlXMXdQQzkwYzNCaGJqNDhkSE53WVc0Z2RHVjRkQzFoYm1Ob2IzSTlJbTFwWkdSc1pTSWdlRDBpTXpjdU5TVWlJSGs5SWpNME1DSStZMjl1ZEhKaFkzUThMM1J6Y0dGdVBqeDBjM0JoYmlCMFpYaDBMV0Z1WTJodmNqMGliV2xrWkd4bElpQjRQU0l6Tnk0MUpTSWdlVDBpTWpnd0lqNTJZV3gxWlR3dmRITndZVzQrUEhSemNHRnVJSFJsZUhRdFlXNWphRzl5UFNKdGFXUmtiR1VpSUhnOUlqTTNMalVsSWlCNVBTSXhOREFpUGp3dmRITndZVzQrUEM5MFpYaDBQanh5WldOMElHTnNZWE56UFNKaUlpQjRQU0l5TVM0NUlpQjVQU0l4TmprdU5TSWdkMmxrZEdnOUlqVTJNaTQwSWlCb1pXbG5hSFE5SWpVMk1pNDBJaTgrUEdjZ2MzUjViR1U5SW1semIyeGhkR2x2YmpwcGMyOXNZWFJsSWo0OGNHRjBhQ0JrUFNKTk5EWXVOallzT1RndU9UTjJMUzR5T0dnMExqZzVWall3TGpjeFNEUTJMalkyZGkwdU1qaElOalV1T1RGak1USXNNQ3d4T0M0ME1pd3pMakU1TERFNExqUXlMREV4TGpFM0xEQXNPUzQwTFRFeExqYzNMREV4TGpJM0xURTVMamcxTERFeExqSTNhQzB4TGpaV09UZ3VOalZvTlM0NE0zWXVNamhhVFRZeUxqZzRMRGd5TGpab01TNDJZelV1T0RNc01DdzNMamMxTFRNdU5EY3NOeTQzTlMweE1YTXRNUzQ1TWkweE1DNDRPUzAzTGpjMUxURXdMamc1YUMweExqWmFJaUJ6ZEhsc1pUMGlabWxzYkRvalpUazJZalZrSWk4K1BDOW5QanhuSUhOMGVXeGxQU0pwYzI5c1lYUnBiMjQ2YVhOdmJHRjBaU0krUEhCaGRHZ2daRDBpVFRFek5TdzVNUzQ0TkdNd0xEVXVNVFl0TWk0eU5pdzNMalV6TFRrdU1qRXNOeTQxTXkwMkxqYzBMREF0T1M0ME15MHlMakk0TFRFeExqVTFMVGd1TmpORE1URXpMRGczTERFeE1pNDBOQ3czT1M0MU1pd3hNRGN1TlRJc056a3VOVEpvTFRFdU5sWTVPQzQyTldnMUxqSTRkaTR5T0VnNE9TNDNkaTB1TWpob05DNDRPVlkyTUM0M01VZzRPUzQzZGkwdU1qaElNVEE1WXpVdU5qWXNNQ3d4T0M0ME55NHlNaXd4T0M0ME55dzVMalEyTERBc055NDFOQzB4TUM0M055dzVMakkzTFRFM0xqTXlMRGt1TlRSMkxqQTVZekV3TGpjMUxEQXNNVE11T1RRc015NDFNaXd4Tmk0MU9DdzVMakUxTERNdU16TXNOeTR4TWl3MExqRXpMRGd1TVRjc05TNDFNeXc0TGpFM0xESXVNaXd3TERJdU5EY3RNeTR6TlN3eUxqUTNMVFZhYlMweU9TMHhNaTQyYURFdU5tTTFMalEwTERBc055NDRNUzB5TGpnMkxEY3VPREV0T1M0ek5Td3dMVFV1TVRFdE1TNDRNaTA1TGpFNExUY3VOemt0T1M0eE9HZ3RNUzQyTWxvaUlITjBlV3hsUFNKbWFXeHNPaU01WWpSaE9HUWlMejQ4TDJjK1BHY2djM1I1YkdVOUltbHpiMnhoZEdsdmJqcHBjMjlzWVhSbElqNDhjR0YwYUNCa1BTSk5NVGM0TGpZMUxEYzVMalk0WXpBc01USXVOVFF0T0M0NE5Td3hPUzQyT1MweE9TNDNNU3d4T1M0Mk9YTXRNVGt1TnpJdE55NHhOUzB4T1M0M01pMHhPUzQyT1ZNeE5EZ3VNRGNzTmpBc01UVTRMamswTERZd0xERTNPQzQyTlN3Mk55NHhOQ3d4TnpndU5qVXNOemt1TmpoYWJTMHhNUzQ0TERCak1DMDRMalF4TFM0MU1pMHhPUzQwTVMwM0xqa3hMVEU1TGpReFV6RTFNU3czTVM0eU55d3hOVEVzTnprdU5qaHpMalV5TERFNUxqUXhMRGN1T1RJc01Ua3VOREZUTVRZMkxqZzFMRGc0TGpFc01UWTJMamcxTERjNUxqWTRXaUlnYzNSNWJHVTlJbVpwYkd3NkkyVTVObUkxWkNJdlBqd3ZaejQ4WnlCemRIbHNaVDBpYVhOdmJHRjBhVzl1T21semIyeGhkR1VpUGp4d1lYUm9JR1E5SWsweU1qWXVOamdzTnprdU5qaGpNQ3d4TWk0MU5DMDRMamtzTVRrdU5qa3RNVGt1T0RNc01Ua3VOamxUTVRnM0xEa3lMakl5TERFNE55dzNPUzQyT0N3eE9UVXVPVElzTmpBc01qQTJMamcxTERZd0xESXlOaTQyT0N3Mk55NHhOQ3d5TWpZdU5qZ3NOemt1TmpoYWJTMHhNUzQ0Tnl3d1l6QXRPQzQwTVMwdU5USXRNVGt1TkRFdE9DMHhPUzQwTVhNdE9Dd3hNUzA0TERFNUxqUXhMalV5TERFNUxqUXhMRGdzTVRrdU5ERlRNakUwTGpneExEZzRMakVzTWpFMExqZ3hMRGM1TGpZNFdpSWdjM1I1YkdVOUltWnBiR3c2SXpsaU5HRTRaQ0l2UGp3dlp6NDhaeUJ6ZEhsc1pUMGlhWE52YkdGMGFXOXVPbWx6YjJ4aGRHVWlQanh3WVhSb0lHUTlJazB5TXpZdU5qa3NPVGd1T1ROMkxTNHlPR2cwTGpnNVZqWXdMamN4YUMwMExqZzVkaTB1TWpob016TXVPVE5NTWpjeUxEY3pMalk1YUMwdU1qZHNMUzR4TVMweFl5MHVPQzAzTGpVMkxUWXVPREl0TVRJdE1UUXVNeTB4TW1ndE5DNDBWamM1TGpFemFDNDJNV00yTGpFNExEQXNNVEF1TWkweUxqVTRMREV3TGpVdE55NDNNbXd1TURVdE1XZ3VNamhzTFM0NU15d3hOeTQzTjJndExqSTRiQzR3TlMweFl5NHlPQzAxTGpFeUxUTXVORGt0Tnk0NE1TMDVMalkzTFRjdU9ERm9MUzQyTVZZNU9DNDJOV2cxTGpnemRpNHlPRm9pSUhOMGVXeGxQU0ptYVd4c09pTTVZalJoT0dNaUx6NDhMMmMrUEdjZ2MzUjViR1U5SW1semIyeGhkR2x2YmpwcGMyOXNZWFJsSWo0OGNHRjBhQ0JrUFNKTk16QTNMamN4TERnM0xqTTRZekFzTnk0ME55MDJMamMxTERFMExqRTNMVEUwTGpjMkxERTBMakUzTFRZdU5ETXNNQzB4TUM0NE9TMDBMakkzTFRFd0xqZzVMVEV3TGpJeExEQXROeTQzTERZdU5qSXRNVFF1TVRnc01UUXVOekl0TVRRdU1UaERNekF6TGpJMkxEYzNMakUyTERNd055NDNNU3c0TVM0ME5Dd3pNRGN1TnpFc09EY3VNemhhYlMwNExqSXpMVFF1TmpSak1DMHlMalkxTFM0MUxUVXVNakl0TWk0M05TMDFMakl5TFRVc01DMDJMalF6TERFekxqZzJMVFl1TkRNc01UZ3VOVFFzTUN3eUxqWTJMalE1TERVdU1UTXNNaTQzTERVdU1UTkRNams0TERFd01TNHhPU3d5T1RrdU5EZ3NPRGd1TURVc01qazVMalE0TERneUxqYzBXaUlnYzNSNWJHVTlJbVpwYkd3Nkl6QmpZalpsWVNJdlBqd3ZaejQ4WnlCemRIbHNaVDBpYVhOdmJHRjBhVzl1T21semIyeGhkR1VpUGp4d1lYUm9JR1E5SWswek1EQXVNVE1zTVRBMUxqUTJZVFF1TmpFc05DNDJNU3d3TERBc01TdzBMalk0TFRRdU56Y3NNeTQ1TXl3ekxqa3pMREFzTUN3eExEUXVNRGtzTkM0eE9Dd3pMakkyTERNdU1qWXNNQ3d3TERBdE1pNDNMRE11TWpsak1Dd3hMakE0TGpRMUxERXVPVE1zTVM0M01Td3hMamt6TERJdU1USXNNQ3cwTFRJdU16UXNOQzAxTGpjMkxEQXRNaTR3TnkwdU5qY3ROQzR6TWkwMExUVXVORGxzTXk0ek55MHlNa2d6TURjdU5td3dMUzR6Tm1nekxqWTFZeTR6TVMwMkxqY3NNaTQxTWkweE1TNDRPQ3c1TGpFNExURXhMamc0TERRdU5Td3dMRFl1TlRjc01pNDBPQ3cyTGpVM0xEVXVNamRoTkM0M05TdzBMamMxTERBc01Dd3hMVFF1T0RJc05XTXRNaTR5TERBdE5DMHhMalEwTFRRdE5DNHlOMkV6TGpBNUxETXVNRGtzTUN3d0xEQXNNaTQ0T0MwekxqSmpNQzB4TGpNMUxTNDFPQzB5TGpJNUxUSXVNRGN0TWk0eU9TMDFMak14TERBdE5pNDROQ3d4TVM0ek9Dd3hMalEwTERFeExqTTRhRE11TW13d0xDNHpObWd0TkM0eU4wd3pNVFlzT1RndU56VmpMUzQ0Tml3MUxqUXRNeTQwTnl3eE1pMDVMamMzTERFeVF6TXdNaTR5T1N3eE1UQXVOeklzTXpBd0xqRXpMREV3T0M0eUxETXdNQzR4TXl3eE1EVXVORFphSWlCemRIbHNaVDBpWm1sc2JEb2pNR05pTm1WaElpOCtQQzluUGp4bklITjBlV3hsUFNKcGMyOXNZWFJwYjI0NmFYTnZiR0YwWlNJK1BIQmhkR2dnWkQwaVRUTTBOUzQ0TlN3NU9DNHhiQzAwTGpBM0xERXVNVFl0TGpnNExURTJhQzQwTkdNdU9EZ3NOaTQwTkN3MExqUTFMREUxTGpZeUxERTBMak0xTERFMUxqWXlMRFVzTUN3NUxURXVOellzT1MwMUxqZ3pMREF0T1M0eU5DMHlOQzA0TGpReExUSTBMVEl4TGpjeVF6TTBNQzQyT0N3Mk5Dd3pORGN1Tnpjc05qQXNNelUyTGpVM0xEWXdZVE01TGpNM0xETTVMak0zTERBc01Dd3hMRGd1TnpVc01TNHlObXcwTGpFNExURXVNVFl1TnpFc01UTXVOVE5vTFM0ME5HTXRMamc0TFRZdU1qRXROQzR6TkMweE15NHhPUzB4TXk0eUxURXpMakU1TFRRdU5Dd3dMVGN1TkRJc01pNHdPQzAzTGpReUxEVXVOallzTUN3NExqUXhMREkwTERjdU1Ea3NNalFzTWpBdU56a3NNQ3czTGpjMUxUZ3VNVE1zTVRJdU5EZ3RNVGN1TkRNc01USXVORGhCTkRFdU5qVXNOREV1TmpVc01Dd3dMREVzTXpRMUxqZzFMRGs0TGpGYUlpQnpkSGxzWlQwaVptbHNiRG9qTlRCaFpUVTRJaTgrUEhCaGRHZ2daRDBpVFRNNE5DNDJNaXc1T0M0NU0zWXRMalEwWXpVdU56SXNNQ3cyTGpJM0xUTXNOaTR5TnkwNUxqUTJWall3TGpnNFl5MDRMamt4TERBdE1USXVPRGNzTlM0ek15MHhNeTQ0TERFekxqWXphQzB1TkRSc01TNDBPQzB4TkM0d04wZzBNVFZzTVM0ME9Dd3hOQzR3TjBnME1UWmpMUzQ1TXkwNExqTXROQzQ0T1MweE15NDJNeTB4TXk0NExURXpMall6VmpnNVl6QXNOaTQwTkM0MU5TdzVMalEyTERZdU1qY3NPUzQwTm5ZdU5EUmFJaUJ6ZEhsc1pUMGlabWxzYkRvak5UQmhaVFU0SWk4K1BDOW5QanhuSUhOMGVXeGxQU0pwYzI5c1lYUnBiMjQ2YVhOdmJHRjBaU0krUEhCaGRHZ2daRDBpVFRRMU5TNDFOQ3c0T0M0ME0yTXpMalEyTERjdU1pdzFMakV4TERFd0xqQTJMRGt1TURjc01UQXVNRFoyTGpRMFNEUTBNaTR4T0hZdExqUTBZelV1TWpJc01DdzBMakU0TFRRdU1UZ3NNUzQwT0MwNUxqazFiQzB4TGpNNUxUTklOREk1TGpFNFl5MDBMRGd1TXpndE1pNDFPU3d4TWk0NU1pd3pMalF6TERFeUxqa3lkaTQwTkVnME1UY3VNWFl0TGpRMFl6UXNNQ3czTGpReUxUUXVOamNzTVRFdU56RXRNVE11TXpac01USXVOekV0TWpVdU56bGFUVFF5T1M0ME5TdzROVWcwTkRKc0xUWXVNVEV0TVRNdU1EaGFJaUJ6ZEhsc1pUMGlabWxzYkRvalpXWTRPVEUySWk4K1BIQmhkR2dnWkQwaVRUVXdOQzQzTVN3NE55NDJObU0wTGpJNUxEa3VOVEVzTlM0MUxERXdMak01TERndU1UUXNNVEF1TVRGMkxqUTFZVE0yTGprMExETTJMamswTERBc01Dd3hMVGd1TnpVc01TNHlObU10Tmk0M05pd3dMVGt1TkMweUxqVTRMVEV4TGpRekxUZ3VOelF0TVM0M05pMDFMak0wTFRNdU1qVXRNVEV1TkRRdE5pNDNOeTB4TVM0ME5HRTBMakEzTERRdU1EY3NNQ3d3TERBdE1TNDRNUzQwTmxZNE9XTXdMRFl1TkRRdU5Ea3NPUzQwTml3MExqVTJMRGt1TkRaMkxqUTBTRFEyTnk0eU5uWXRMalEwWXpVdU5Td3dMRFV1TlMwekxEVXVOUzA1TGpRMlZqY3dMak16WXpBdE5pNDJOU3d3TFRrdU5EWXROUzQxTFRrdU5EWjJMUzQwTTJneU1TNHpPWFl1TkROakxUUXVNRGNzTUMwMExqVTJMRE10TkM0MU5pdzVMalEyVmpjNUxqRnNOeTAzTGpZM1l6SXVNell0TWk0MU15dzFMak01TFRZdU1UWXNOUzR6T1MwNExqUXhMREF0TVM0ME9TMHhMVEl1TVRVdE15NDJNeTB5TGpFMWRpMHVORE5vTVRZdU5qWjJMalF6WXkwM0xEQXRNVFF1Tmpnc055NHpNaTB4T0N3eE1DNDVOV3d0Tmk0ME9DdzNZVEU0TERFNExEQXNNQ3d4TERndU1qUXRNbU0xTGpVMkxEQXNPQzR4T1N3ekxqTXNNVEV1TkRRc01UQXVPRFJhSWlCemRIbHNaVDBpWm1sc2JEb2paV1k0T1RFMklpOCtQQzluUGp4bklITjBlV3hsUFNKcGMyOXNZWFJwYjI0NmFYTnZiR0YwWlNJK1BIQmhkR2dnWkQwaVRUVTFNaTR5TERjekxqWTVhQzB1TWpoc0xTNHhNUzB4WXkwdU9DMDNMalUyTFRZdU9ESXRNVEl0TVRRdU15MHhNa2cxTXpKV056a3VNVE5vTGpZeFl6WXVNVGdzTUN3eE1DNHlMVEl1TlRnc01UQXVOUzAzTGpjeWJDNHdOaTB4YUM0eU4yd3RMamt6TERFM0xqYzNhQzB1TWpoc0xqQTJMVEZqTGpJM0xUVXVNVEl0TXk0MUxUY3VPREV0T1M0Mk9DMDNMamd4U0RVek1sWTVNbU13TERVdU16TXVOakVzTmk0M0xEUXVOQ3cyTGpjc09TNDROeXd3TERFMkxUWXVNVFVzTVRjdU16VXRNVFZzTGpJdE1TNHlOR2d1TWpkc0xUSXVOalFzTVRZdU5XZ3RNelV1T0hZdExqSTRhRFF1T0RsV05qQXVOekZvTFRRdU9EbDJMUzR5TjJnek5Wb2lJSE4wZVd4bFBTSm1hV3hzT2lNMU1HRmxOVGdpTHo0OEwyYytQSFJsZUhRZ1kyeGhjM005SW13aUlIUnlZVzV6Wm05eWJUMGlkSEpoYm5Oc1lYUmxLREl6TlM0eE5TQXlOalVwSWo1MmFYUmhiR2xyTG1WMGFEd3ZkR1Y0ZEQ0Z1BIUmxlSFFnWTJ4aGMzTTlJbTBpSUhSeVlXNXpabTl5YlQwaWRISmhibk5zWVhSbEtESTJNeTQwT0NBeU9UVXBJajV6YVdkdVpYSThMM1JsZUhRK0lEeDBaWGgwSUdOc1lYTnpQU0p0SWlCMGNtRnVjMlp2Y20wOUluUnlZVzV6YkdGMFpTZ3lORFV1TmpRZ016Y3pLU0krY21WamFYQnBaVzUwUEM5MFpYaDBQand2YzNablBnPT0ifQ==\n")])])]),M("p",[T._v("在使用 base64 格式解碼後可以得到以下資料:")]),T._v(" "),M("div",{staticClass:"language-json extra-class"},[M("pre",{pre:!0,attrs:{class:"language-json"}},[M("code",[M("span",{pre:!0,attrs:{class:"token punctuation"}},[T._v("{")]),T._v("\n "),M("span",{pre:!0,attrs:{class:"token property"}},[T._v('"signed_to"')]),M("span",{pre:!0,attrs:{class:"token operator"}},[T._v(":")]),M("span",{pre:!0,attrs:{class:"token string"}},[T._v('"hydai.eth"')]),M("span",{pre:!0,attrs:{class:"token punctuation"}},[T._v(",")]),T._v("\n "),M("span",{pre:!0,attrs:{class:"token property"}},[T._v('"external_url"')]),M("span",{pre:!0,attrs:{class:"token operator"}},[T._v(":")]),M("span",{pre:!0,attrs:{class:"token string"}},[T._v('"https://proofofstake.gitcoin.co/"')]),M("span",{pre:!0,attrs:{class:"token punctuation"}},[T._v(",")]),T._v("\n "),M("span",{pre:!0,attrs:{class:"token property"}},[T._v('"timestamp"')]),M("span",{pre:!0,attrs:{class:"token operator"}},[T._v(":")]),M("span",{pre:!0,attrs:{class:"token string"}},[T._v('"1662830690"')]),M("span",{pre:!0,attrs:{class:"token punctuation"}},[T._v(",")]),T._v("\n "),M("span",{pre:!0,attrs:{class:"token property"}},[T._v('"pledge"')]),M("span",{pre:!0,attrs:{class:"token operator"}},[T._v(":")]),M("span",{pre:!0,attrs:{class:"token string"}},[T._v('"50000000000000000"')]),M("span",{pre:!0,attrs:{class:"token punctuation"}},[T._v(",")]),T._v("\n "),M("span",{pre:!0,attrs:{class:"token property"}},[T._v('"message"')]),M("span",{pre:!0,attrs:{class:"token operator"}},[T._v(":")]),M("span",{pre:!0,attrs:{class:"token string"}},[T._v('"Thank you for supporting public goods, and enjoy the book!"')]),M("span",{pre:!0,attrs:{class:"token punctuation"}},[T._v(",")]),T._v("\n "),M("span",{pre:!0,attrs:{class:"token property"}},[T._v('"image"')]),M("span",{pre:!0,attrs:{class:"token operator"}},[T._v(":")]),M("span",{pre:!0,attrs:{class:"token string"}},[T._v('"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MDYuMiIgaGVpZ2h0PSI4MTkuNCIgdmlld0JveD0iMCAwIDYwNi4yIDgxOS40Ij48ZGVmcz48c3R5bGU+LmF7ZmlsbDojZmZmO30uYntmaWxsOm5vbmU7c3Ryb2tlOiNkOWM4ZGI7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLXdpZHRoOjJweDt9LmMsLmQsLmUsLmYsLmcsLmgsLmksLmosLmssLmwsLm0sLm4sLm97aXNvbGF0aW9uOmlzb2xhdGU7fS5jLC5kLC5lLC5mLC5nLC5pLC5qLC5re2ZvbnQtc2l6ZTo1NXB4O30uYywuZXtmaWxsOiNlOTZiNWQ7fS5jLC5kLC5lLC5mLC5nLC5re2ZvbnQtZmFtaWx5Okx1c3REaXNwbGF5LURpZG9uZSwgTHVzdCBEaWRvbmU7fS5kLC5me2ZpbGw6IzliNGE4ZDt9LmV7bGV0dGVyLXNwYWNpbmc6MC4wMmVtO30uZntsZXR0ZXItc3BhY2luZzowLjAyZW07fS5ne2ZpbGw6IzliNGE4Yzt9Lmh7Zm9udC1zaXplOjQ1cHg7ZmlsbDojMGNiNmVhO2ZvbnQtZmFtaWx5Okx1c3QtSXRhbGljLCBMdXN0O2ZvbnQtc3R5bGU6aXRhbGljO30uaSwua3tmaWxsOiM1MGFlNTg7fS5pLC5qe2ZvbnQtZmFtaWx5Okx1c3QtUmVndWxhciwgTHVzdDtsZXR0ZXItc3BhY2luZzowLjA1ZW07fS5qe2ZpbGw6I2VmODkxNjt9LmwsLm17Zm9udC1zaXplOjI5Ljk5cHg7fS5sLC5ue2ZvbnQtZmFtaWx5OkFyaWFsLUJvbGRNVCwgQXJpYWw7Zm9udC13ZWlnaHQ6NzAwO30ubSwub3tmb250LWZhbWlseTpBcmlhbE1ULCBBcmlhbDsgbWFyZ2luLWxlZnQ6IGF1dG87IG1hcmdpbi1yaWdodDogYXV0bzsgd2lkdGg6IDQwJTt9Lm57Zm9udC1zaXplOjIwcHg7fS5ve2ZvbnQtc2l6ZToxOHB4O308L3N0eWxlPjwvZGVmcz48cmVjdCBjbGFzcz0iYSIgd2lkdGg9IjYwNi4yIiBoZWlnaHQ9IjgxOS40Ii8+PHRleHQgY2xhc3M9Im4iPjx0c3BhbiBjbGFzcz0ibiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNTAlIiB5PSI0MiUiPmh5ZGFpLmV0aDwvdHNwYW4+PC90ZXh0Pjx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDc1IDM1Mi44NSkiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtZmFtaWx5PSJBcmlhbE1ULCBBcmlhbCI+PHRzcGFuIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3LjUlIiB5PSIyMDAiPjE2NjI4MzA2OTA8L3RzcGFuPjx0c3BhbiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzNy41JSIgeT0iMjYwIj41MDAwMDAwMDAwMDAwMDAwMCAod2VpKTwvdHNwYW4+PHRzcGFuIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3LjUlIiB5PSIzMjAiPjB4NWJmNWJjYzUzNjJmODg3MjExNjdjMTA2OGI1OGM2MGNhZDA3NWFhYzwvdHNwYW4+PHRzcGFuIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3LjUlIiB5PSIxMjAiPiJUaGFuayB5b3UgZm9yIHN1cHBvcnRpbmcgcHVibGljIGdvb2RzLCBhbmQgZW5qb3kgdGhlIGJvb2shIjwvdHNwYW4+PHRzcGFuIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3LjUlIiB5PSIyMjAiPm1pbnQgdGltZXN0YW1wPC90c3Bhbj48dHNwYW4gdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzcuNSUiIHk9IjM0MCI+Y29udHJhY3Q8L3RzcGFuPjx0c3BhbiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzNy41JSIgeT0iMjgwIj52YWx1ZTwvdHNwYW4+PHRzcGFuIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3LjUlIiB5PSIxNDAiPjwvdHNwYW4+PC90ZXh0PjxyZWN0IGNsYXNzPSJiIiB4PSIyMS45IiB5PSIxNjkuNSIgd2lkdGg9IjU2Mi40IiBoZWlnaHQ9IjU2Mi40Ii8+PGcgc3R5bGU9Imlzb2xhdGlvbjppc29sYXRlIj48cGF0aCBkPSJNNDYuNjYsOTguOTN2LS4yOGg0Ljg5VjYwLjcxSDQ2LjY2di0uMjhINjUuOTFjMTIsMCwxOC40MiwzLjE5LDE4LjQyLDExLjE3LDAsOS40LTExLjc3LDExLjI3LTE5Ljg1LDExLjI3aC0xLjZWOTguNjVoNS44M3YuMjhaTTYyLjg4LDgyLjZoMS42YzUuODMsMCw3Ljc1LTMuNDcsNy43NS0xMXMtMS45Mi0xMC44OS03Ljc1LTEwLjg5aC0xLjZaIiBzdHlsZT0iZmlsbDojZTk2YjVkIi8+PC9nPjxnIHN0eWxlPSJpc29sYXRpb246aXNvbGF0ZSI+PHBhdGggZD0iTTEzNSw5MS44NGMwLDUuMTYtMi4yNiw3LjUzLTkuMjEsNy41My02Ljc0LDAtOS40My0yLjI4LTExLjU1LTguNjNDMTEzLDg3LDExMi40NCw3OS41MiwxMDcuNTIsNzkuNTJoLTEuNlY5OC42NWg1LjI4di4yOEg4OS43di0uMjhoNC44OVY2MC43MUg4OS43di0uMjhIMTA5YzUuNjYsMCwxOC40Ny4yMiwxOC40Nyw5LjQ2LDAsNy41NC0xMC43Nyw5LjI3LTE3LjMyLDkuNTR2LjA5YzEwLjc1LDAsMTMuOTQsMy41MiwxNi41OCw5LjE1LDMuMzMsNy4xMiw0LjEzLDguMTcsNS41Myw4LjE3LDIuMiwwLDIuNDctMy4zNSwyLjQ3LTVabS0yOS0xMi42aDEuNmM1LjQ0LDAsNy44MS0yLjg2LDcuODEtOS4zNSwwLTUuMTEtMS44Mi05LjE4LTcuNzktOS4xOGgtMS42MloiIHN0eWxlPSJmaWxsOiM5YjRhOGQiLz48L2c+PGcgc3R5bGU9Imlzb2xhdGlvbjppc29sYXRlIj48cGF0aCBkPSJNMTc4LjY1LDc5LjY4YzAsMTIuNTQtOC44NSwxOS42OS0xOS43MSwxOS42OXMtMTkuNzItNy4xNS0xOS43Mi0xOS42OVMxNDguMDcsNjAsMTU4Ljk0LDYwLDE3OC42NSw2Ny4xNCwxNzguNjUsNzkuNjhabS0xMS44LDBjMC04LjQxLS41Mi0xOS40MS03LjkxLTE5LjQxUzE1MSw3MS4yNywxNTEsNzkuNjhzLjUyLDE5LjQxLDcuOTIsMTkuNDFTMTY2Ljg1LDg4LjEsMTY2Ljg1LDc5LjY4WiIgc3R5bGU9ImZpbGw6I2U5NmI1ZCIvPjwvZz48ZyBzdHlsZT0iaXNvbGF0aW9uOmlzb2xhdGUiPjxwYXRoIGQ9Ik0yMjYuNjgsNzkuNjhjMCwxMi41NC04LjksMTkuNjktMTkuODMsMTkuNjlTMTg3LDkyLjIyLDE4Nyw3OS42OCwxOTUuOTIsNjAsMjA2Ljg1LDYwLDIyNi42OCw2Ny4xNCwyMjYuNjgsNzkuNjhabS0xMS44NywwYzAtOC40MS0uNTItMTkuNDEtOC0xOS40MXMtOCwxMS04LDE5LjQxLjUyLDE5LjQxLDgsMTkuNDFTMjE0LjgxLDg4LjEsMjE0LjgxLDc5LjY4WiIgc3R5bGU9ImZpbGw6IzliNGE4ZCIvPjwvZz48ZyBzdHlsZT0iaXNvbGF0aW9uOmlzb2xhdGUiPjxwYXRoIGQ9Ik0yMzYuNjksOTguOTN2LS4yOGg0Ljg5VjYwLjcxaC00Ljg5di0uMjhoMzMuOTNMMjcyLDczLjY5aC0uMjdsLS4xMS0xYy0uOC03LjU2LTYuODItMTItMTQuMy0xMmgtNC40Vjc5LjEzaC42MWM2LjE4LDAsMTAuMi0yLjU4LDEwLjUtNy43MmwuMDUtMWguMjhsLS45MywxNy43N2gtLjI4bC4wNS0xYy4yOC01LjEyLTMuNDktNy44MS05LjY3LTcuODFoLS42MVY5OC42NWg1Ljgzdi4yOFoiIHN0eWxlPSJmaWxsOiM5YjRhOGMiLz48L2c+PGcgc3R5bGU9Imlzb2xhdGlvbjppc29sYXRlIj48cGF0aCBkPSJNMzA3LjcxLDg3LjM4YzAsNy40Ny02Ljc1LDE0LjE3LTE0Ljc2LDE0LjE3LTYuNDMsMC0xMC44OS00LjI3LTEwLjg5LTEwLjIxLDAtNy43LDYuNjItMTQuMTgsMTQuNzItMTQuMThDMzAzLjI2LDc3LjE2LDMwNy43MSw4MS40NCwzMDcuNzEsODcuMzhabS04LjIzLTQuNjRjMC0yLjY1LS41LTUuMjItMi43NS01LjIyLTUsMC02LjQzLDEzLjg2LTYuNDMsMTguNTQsMCwyLjY2LjQ5LDUuMTMsMi43LDUuMTNDMjk4LDEwMS4xOSwyOTkuNDgsODguMDUsMjk5LjQ4LDgyLjc0WiIgc3R5bGU9ImZpbGw6IzBjYjZlYSIvPjwvZz48ZyBzdHlsZT0iaXNvbGF0aW9uOmlzb2xhdGUiPjxwYXRoIGQ9Ik0zMDAuMTMsMTA1LjQ2YTQuNjEsNC42MSwwLDAsMSw0LjY4LTQuNzcsMy45MywzLjkzLDAsMCwxLDQuMDksNC4xOCwzLjI2LDMuMjYsMCwwLDAtMi43LDMuMjljMCwxLjA4LjQ1LDEuOTMsMS43MSwxLjkzLDIuMTIsMCw0LTIuMzQsNC01Ljc2LDAtMi4wNy0uNjctNC4zMi00LTUuNDlsMy4zNy0yMkgzMDcuNmwwLS4zNmgzLjY1Yy4zMS02LjcsMi41Mi0xMS44OCw5LjE4LTExLjg4LDQuNSwwLDYuNTcsMi40OCw2LjU3LDUuMjdhNC43NSw0Ljc1LDAsMCwxLTQuODIsNWMtMi4yLDAtNC0xLjQ0LTQtNC4yN2EzLjA5LDMuMDksMCwwLDAsMi44OC0zLjJjMC0xLjM1LS41OC0yLjI5LTIuMDctMi4yOS01LjMxLDAtNi44NCwxMS4zOCwxLjQ0LDExLjM4aDMuMmwwLC4zNmgtNC4yN0wzMTYsOTguNzVjLS44Niw1LjQtMy40NywxMi05Ljc3LDEyQzMwMi4yOSwxMTAuNzIsMzAwLjEzLDEwOC4yLDMwMC4xMywxMDUuNDZaIiBzdHlsZT0iZmlsbDojMGNiNmVhIi8+PC9nPjxnIHN0eWxlPSJpc29sYXRpb246aXNvbGF0ZSI+PHBhdGggZD0iTTM0NS44NSw5OC4xbC00LjA3LDEuMTYtLjg4LTE2aC40NGMuODgsNi40NCw0LjQ1LDE1LjYyLDE0LjM1LDE1LjYyLDUsMCw5LTEuNzYsOS01LjgzLDAtOS4yNC0yNC04LjQxLTI0LTIxLjcyQzM0MC42OCw2NCwzNDcuNzcsNjAsMzU2LjU3LDYwYTM5LjM3LDM5LjM3LDAsMCwxLDguNzUsMS4yNmw0LjE4LTEuMTYuNzEsMTMuNTNoLS40NGMtLjg4LTYuMjEtNC4zNC0xMy4xOS0xMy4yLTEzLjE5LTQuNCwwLTcuNDIsMi4wOC03LjQyLDUuNjYsMCw4LjQxLDI0LDcuMDksMjQsMjAuNzksMCw3Ljc1LTguMTMsMTIuNDgtMTcuNDMsMTIuNDhBNDEuNjUsNDEuNjUsMCwwLDEsMzQ1Ljg1LDk4LjFaIiBzdHlsZT0iZmlsbDojNTBhZTU4Ii8+PHBhdGggZD0iTTM4NC42Miw5OC45M3YtLjQ0YzUuNzIsMCw2LjI3LTMsNi4yNy05LjQ2VjYwLjg4Yy04LjkxLDAtMTIuODcsNS4zMy0xMy44LDEzLjYzaC0uNDRsMS40OC0xNC4wN0g0MTVsMS40OCwxNC4wN0g0MTZjLS45My04LjMtNC44OS0xMy42My0xMy44LTEzLjYzVjg5YzAsNi40NC41NSw5LjQ2LDYuMjcsOS40NnYuNDRaIiBzdHlsZT0iZmlsbDojNTBhZTU4Ii8+PC9nPjxnIHN0eWxlPSJpc29sYXRpb246aXNvbGF0ZSI+PHBhdGggZD0iTTQ1NS41NCw4OC40M2MzLjQ2LDcuMiw1LjExLDEwLjA2LDkuMDcsMTAuMDZ2LjQ0SDQ0Mi4xOHYtLjQ0YzUuMjIsMCw0LjE4LTQuMTgsMS40OC05Ljk1bC0xLjM5LTNINDI5LjE4Yy00LDguMzgtMi41OSwxMi45MiwzLjQzLDEyLjkydi40NEg0MTcuMXYtLjQ0YzQsMCw3LjQyLTQuNjcsMTEuNzEtMTMuMzZsMTIuNzEtMjUuNzlaTTQyOS40NSw4NUg0NDJsLTYuMTEtMTMuMDhaIiBzdHlsZT0iZmlsbDojZWY4OTE2Ii8+PHBhdGggZD0iTTUwNC43MSw4Ny42NmM0LjI5LDkuNTEsNS41LDEwLjM5LDguMTQsMTAuMTF2LjQ1YTM2Ljk0LDM2Ljk0LDAsMCwxLTguNzUsMS4yNmMtNi43NiwwLTkuNC0yLjU4LTExLjQzLTguNzQtMS43Ni01LjM0LTMuMjUtMTEuNDQtNi43Ny0xMS40NGE0LjA3LDQuMDcsMCwwLDAtMS44MS40NlY4OWMwLDYuNDQuNDksOS40Niw0LjU2LDkuNDZ2LjQ0SDQ2Ny4yNnYtLjQ0YzUuNSwwLDUuNS0zLDUuNS05LjQ2VjcwLjMzYzAtNi42NSwwLTkuNDYtNS41LTkuNDZ2LS40M2gyMS4zOXYuNDNjLTQuMDcsMC00LjU2LDMtNC41Niw5LjQ2Vjc5LjFsNy03LjY3YzIuMzYtMi41Myw1LjM5LTYuMTYsNS4zOS04LjQxLDAtMS40OS0xLTIuMTUtMy42My0yLjE1di0uNDNoMTYuNjZ2LjQzYy03LDAtMTQuNjgsNy4zMi0xOCwxMC45NWwtNi40OCw3YTE4LDE4LDAsMCwxLDguMjQtMmM1LjU2LDAsOC4xOSwzLjMsMTEuNDQsMTAuODRaIiBzdHlsZT0iZmlsbDojZWY4OTE2Ii8+PC9nPjxnIHN0eWxlPSJpc29sYXRpb246aXNvbGF0ZSI+PHBhdGggZD0iTTU1Mi4yLDczLjY5aC0uMjhsLS4xMS0xYy0uOC03LjU2LTYuODItMTItMTQuMy0xMkg1MzJWNzkuMTNoLjYxYzYuMTgsMCwxMC4yLTIuNTgsMTAuNS03LjcybC4wNi0xaC4yN2wtLjkzLDE3Ljc3aC0uMjhsLjA2LTFjLjI3LTUuMTItMy41LTcuODEtOS42OC03LjgxSDUzMlY5MmMwLDUuMzMuNjEsNi43LDQuNCw2LjcsOS44NywwLDE2LTYuMTUsMTcuMzUtMTVsLjItMS4yNGguMjdsLTIuNjQsMTYuNWgtMzUuOHYtLjI4aDQuODlWNjAuNzFoLTQuODl2LS4yN2gzNVoiIHN0eWxlPSJmaWxsOiM1MGFlNTgiLz48L2c+PHRleHQgY2xhc3M9ImwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIzNS4xNSAyNjUpIj52aXRhbGlrLmV0aDwvdGV4dD4gPHRleHQgY2xhc3M9Im0iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI2My40OCAyOTUpIj5zaWduZXI8L3RleHQ+IDx0ZXh0IGNsYXNzPSJtIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNDUuNjQgMzczKSI+cmVjaXBpZW50PC90ZXh0Pjwvc3ZnPg=="')]),T._v("\n"),M("span",{pre:!0,attrs:{class:"token punctuation"}},[T._v("}")]),T._v("\n")])])]),M("h2",{attrs:{id:"結語"}},[M("a",{staticClass:"header-anchor",attrs:{href:"#結語"}},[T._v("#")]),T._v(" 結語")]),T._v(" "),M("p",[T._v("通過 URI JSON Schema 我們可以把 NFT 的詳細資訊給記錄在合約中。然而,Proof-of-Stake: Pages 的圖片非常簡單,因此可以使用 SVG 圖片格式直接編碼在 URI 內。")]),T._v(" "),M("p",[T._v("但,如果 NFT 代表的是一部 4K 影片、一張 8K 圖片等大型檔案,由於儲存成本會變得過高,因此會改用連結到該檔案的方式取代。")])])}),[],!1,null,null,null);M.default=U.exports}}]); \ No newline at end of file diff --git a/assets/js/46.67cc6973.js b/assets/js/46.a01f013b.js similarity index 99% rename from assets/js/46.67cc6973.js rename to assets/js/46.a01f013b.js index 47ba851..901e5ab 100644 --- a/assets/js/46.67cc6973.js +++ b/assets/js/46.a01f013b.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[46],{368:function(t,s,a){"use strict";a.r(s);var n=a(17),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"實例解析-proof-of-stake-書籍的捐款合約-part-2"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#實例解析-proof-of-stake-書籍的捐款合約-part-2"}},[t._v("#")]),t._v(" 實例解析 - Proof of Stake 書籍的捐款合約 Part 2")]),t._v(" "),s("h2",{attrs:{id:"合約原始碼"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#合約原始碼"}},[t._v("#")]),t._v(" 合約原始碼")]),t._v(" "),s("p",[s("a",{attrs:{href:"https://etherscan.io/address/0x5bf5bcc5362f88721167c1068b58c60cad075aac#code",target:"_blank",rel:"noopener noreferrer"}},[t._v("合約原始碼請點此"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"proofofstake-pages-sol-引用的函式庫與介面"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#proofofstake-pages-sol-引用的函式庫與介面"}},[t._v("#")]),t._v(" "),s("code",[t._v("ProofOfStake_Pages.sol")]),t._v(" 引用的函式庫與介面")]),t._v(" "),s("p",[t._v("ProofOfStake_Pages 合約中引入的函式庫與介面,可以看到以下的結構("),s("code",[t._v("*")]),t._v(" 為本日說明的範圍)")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[t._v("ProofOfStake_Pages\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Ownable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ReentrancyGuard"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721Receiver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721Metadata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Counters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n")])])]),s("h3",{attrs:{id:"counters-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#counters-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("Counters.sol")])]),t._v(" "),s("p",[s("code",[t._v("Counters")]),t._v(" 是一個輔助合約,他提供了計數器的功能:")]),t._v(" "),s("ol",[s("li",[t._v("提供一個資料結構 "),s("code",[t._v("Counter")]),t._v(" 為一個 "),s("code",[t._v("uint256")]),t._v(" 的計數器,且初始值為 "),s("code",[t._v("0")]),t._v("。")]),t._v(" "),s("li",[t._v("當要拿到當前的數值時,呼叫 "),s("code",[t._v("current(Counter)")]),t._v(" 而不應該直接讀取 "),s("code",[t._v("Counter._value")])]),t._v(" "),s("li",[t._v("要增加一次計數時,呼叫 "),s("code",[t._v("increment(Counter)")])]),t._v(" "),s("li",[t._v("要減少一次計數時,呼叫 "),s("code",[t._v("decrement(Counter)")])]),t._v(" "),s("li",[t._v("若要重設計數器,呼叫 "),s("code",[t._v("reset(Counter)")])])]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SPDX-License-Identifier: MIT")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("library")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Counters")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Counter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This variable should never be directly accessed by users of the library: interactions must be restricted to")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// this feature: see https://github.com/ethereum/solidity/issues/4637")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" _value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// default: 0")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("current")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Counter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("storage")]),t._v(" counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("increment")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Counter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("storage")]),t._v(" counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n unchecked "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("decrement")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Counter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("storage")]),t._v(" counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Counter: decrement overflow"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n unchecked "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("reset")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Counter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("storage")]),t._v(" counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h3",{attrs:{id:"strings-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#strings-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("Strings.sol")])]),t._v(" "),s("p",[s("code",[t._v("Strings")]),t._v(" 是一個輔助合約,他提供了字串處理的功能:")]),t._v(" "),s("ol",[s("li",[s("code",[t._v("toString(uint256 value)")]),t._v(":將一個 "),s("code",[t._v("uint256")]),t._v(" 的非負整數轉換成以 "),s("code",[t._v("ASCII")]),t._v(" 編碼的字串。")]),t._v(" "),s("li",[s("code",[t._v("toHexString(uint256 value)")]),t._v(":將一個 "),s("code",[t._v("uint256")]),t._v(" 的非負整數轉換成以 "),s("code",[t._v("ASCII")]),t._v(" 編碼且以十六進位表示的字串。")]),t._v(" "),s("li",[s("code",[t._v("toHexString(uint256 value, uint256 length)")]),t._v(":將一個 "),s("code",[t._v("uint256")]),t._v(" 的非負整數轉換成以 "),s("code",[t._v("ASCII")]),t._v(" 編碼且以十六進位表示的字串,並指定輸出的字串長度。")])]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SPDX-License-Identifier: MIT")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev String operations.\n */")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("library")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Strings")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes16")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" _HEX_SYMBOLS "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0123456789abcdef"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pure")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Inspired by OraclizeAPI's implementation - MIT licence")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" temp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" digits"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("while")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("temp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n digits"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n temp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" buffer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("digits"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("while")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n digits "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n buffer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("digits"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("48")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("buffer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toHexString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pure")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0x00"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" temp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("while")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("temp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n length"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n temp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toHexString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" length"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toHexString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" length"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pure")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" buffer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n buffer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n buffer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"x"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" i "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n buffer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _HEX_SYMBOLS"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Strings: hex length insufficient"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("buffer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h3",{attrs:{id:"context-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#context-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("Context.sol")])]),t._v(" "),s("p",[s("code",[t._v("Context")]),t._v(" 是一個輔助合約,他提供幾個輔助函式,用以查詢當前執行環境的語境中的發送者("),s("code",[t._v("msg.sender")]),t._v(")與發送資料("),s("code",[t._v("msg.data")]),t._v(")。")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SPDX-License-Identifier: MIT")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */")]),t._v("\nabstract "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("contract")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Context")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgData")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("calldata")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[46],{367:function(t,s,a){"use strict";a.r(s);var n=a(17),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"實例解析-proof-of-stake-書籍的捐款合約-part-2"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#實例解析-proof-of-stake-書籍的捐款合約-part-2"}},[t._v("#")]),t._v(" 實例解析 - Proof of Stake 書籍的捐款合約 Part 2")]),t._v(" "),s("h2",{attrs:{id:"合約原始碼"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#合約原始碼"}},[t._v("#")]),t._v(" 合約原始碼")]),t._v(" "),s("p",[s("a",{attrs:{href:"https://etherscan.io/address/0x5bf5bcc5362f88721167c1068b58c60cad075aac#code",target:"_blank",rel:"noopener noreferrer"}},[t._v("合約原始碼請點此"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"proofofstake-pages-sol-引用的函式庫與介面"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#proofofstake-pages-sol-引用的函式庫與介面"}},[t._v("#")]),t._v(" "),s("code",[t._v("ProofOfStake_Pages.sol")]),t._v(" 引用的函式庫與介面")]),t._v(" "),s("p",[t._v("ProofOfStake_Pages 合約中引入的函式庫與介面,可以看到以下的結構("),s("code",[t._v("*")]),t._v(" 為本日說明的範圍)")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[t._v("ProofOfStake_Pages\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Ownable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ReentrancyGuard"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721Receiver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721Metadata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Counters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n")])])]),s("h3",{attrs:{id:"counters-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#counters-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("Counters.sol")])]),t._v(" "),s("p",[s("code",[t._v("Counters")]),t._v(" 是一個輔助合約,他提供了計數器的功能:")]),t._v(" "),s("ol",[s("li",[t._v("提供一個資料結構 "),s("code",[t._v("Counter")]),t._v(" 為一個 "),s("code",[t._v("uint256")]),t._v(" 的計數器,且初始值為 "),s("code",[t._v("0")]),t._v("。")]),t._v(" "),s("li",[t._v("當要拿到當前的數值時,呼叫 "),s("code",[t._v("current(Counter)")]),t._v(" 而不應該直接讀取 "),s("code",[t._v("Counter._value")])]),t._v(" "),s("li",[t._v("要增加一次計數時,呼叫 "),s("code",[t._v("increment(Counter)")])]),t._v(" "),s("li",[t._v("要減少一次計數時,呼叫 "),s("code",[t._v("decrement(Counter)")])]),t._v(" "),s("li",[t._v("若要重設計數器,呼叫 "),s("code",[t._v("reset(Counter)")])])]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SPDX-License-Identifier: MIT")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("library")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Counters")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Counter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This variable should never be directly accessed by users of the library: interactions must be restricted to")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// this feature: see https://github.com/ethereum/solidity/issues/4637")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" _value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// default: 0")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("current")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Counter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("storage")]),t._v(" counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("increment")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Counter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("storage")]),t._v(" counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n unchecked "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("decrement")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Counter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("storage")]),t._v(" counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Counter: decrement overflow"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n unchecked "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("reset")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Counter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("storage")]),t._v(" counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h3",{attrs:{id:"strings-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#strings-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("Strings.sol")])]),t._v(" "),s("p",[s("code",[t._v("Strings")]),t._v(" 是一個輔助合約,他提供了字串處理的功能:")]),t._v(" "),s("ol",[s("li",[s("code",[t._v("toString(uint256 value)")]),t._v(":將一個 "),s("code",[t._v("uint256")]),t._v(" 的非負整數轉換成以 "),s("code",[t._v("ASCII")]),t._v(" 編碼的字串。")]),t._v(" "),s("li",[s("code",[t._v("toHexString(uint256 value)")]),t._v(":將一個 "),s("code",[t._v("uint256")]),t._v(" 的非負整數轉換成以 "),s("code",[t._v("ASCII")]),t._v(" 編碼且以十六進位表示的字串。")]),t._v(" "),s("li",[s("code",[t._v("toHexString(uint256 value, uint256 length)")]),t._v(":將一個 "),s("code",[t._v("uint256")]),t._v(" 的非負整數轉換成以 "),s("code",[t._v("ASCII")]),t._v(" 編碼且以十六進位表示的字串,並指定輸出的字串長度。")])]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SPDX-License-Identifier: MIT")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev String operations.\n */")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("library")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Strings")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes16")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" _HEX_SYMBOLS "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0123456789abcdef"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pure")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Inspired by OraclizeAPI's implementation - MIT licence")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" temp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" digits"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("while")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("temp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n digits"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n temp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" buffer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("digits"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("while")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n digits "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n buffer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("digits"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("48")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("buffer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toHexString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pure")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0x00"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" temp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("while")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("temp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n length"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n temp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toHexString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" length"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toHexString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" length"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pure")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" buffer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n buffer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n buffer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"x"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" i "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n buffer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _HEX_SYMBOLS"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Strings: hex length insufficient"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("buffer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h3",{attrs:{id:"context-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#context-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("Context.sol")])]),t._v(" "),s("p",[s("code",[t._v("Context")]),t._v(" 是一個輔助合約,他提供幾個輔助函式,用以查詢當前執行環境的語境中的發送者("),s("code",[t._v("msg.sender")]),t._v(")與發送資料("),s("code",[t._v("msg.data")]),t._v(")。")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SPDX-License-Identifier: MIT")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */")]),t._v("\nabstract "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("contract")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Context")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgData")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("calldata")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/47.d878efb0.js b/assets/js/47.2941f6f7.js similarity index 99% rename from assets/js/47.d878efb0.js rename to assets/js/47.2941f6f7.js index 268fa3b..cc09423 100644 --- a/assets/js/47.d878efb0.js +++ b/assets/js/47.2941f6f7.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[47],{367:function(t,s,n){"use strict";n.r(s);var a=n(17),e=Object(a.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"實例解析-proof-of-stake-書籍的捐款合約-part-3"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#實例解析-proof-of-stake-書籍的捐款合約-part-3"}},[t._v("#")]),t._v(" 實例解析 - Proof of Stake 書籍的捐款合約 Part 3")]),t._v(" "),s("h2",{attrs:{id:"合約原始碼"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#合約原始碼"}},[t._v("#")]),t._v(" 合約原始碼")]),t._v(" "),s("p",[s("a",{attrs:{href:"https://etherscan.io/address/0x5bf5bcc5362f88721167c1068b58c60cad075aac#code",target:"_blank",rel:"noopener noreferrer"}},[t._v("合約原始碼請點此"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"proofofstake-pages-sol-引用的函式庫與介面"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#proofofstake-pages-sol-引用的函式庫與介面"}},[t._v("#")]),t._v(" "),s("code",[t._v("ProofOfStake_Pages.sol")]),t._v(" 引用的函式庫與介面")]),t._v(" "),s("p",[t._v("ProofOfStake_Pages 合約中引入的函式庫與介面,可以看到以下的結構("),s("code",[t._v("*")]),t._v(" 為本日說明的範圍)")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[t._v("ProofOfStake_Pages\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Ownable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ReentrancyGuard"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721Receiver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721Metadata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Counters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n")])])]),s("h3",{attrs:{id:"ownable-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#ownable-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("Ownable.sol")])]),t._v(" "),s("p",[s("code",[t._v("Ownable")]),t._v(" 是一個輔助合約,讓繼承的合約可以擁有對合約的存取管理權限,它提供了以下功能:")]),t._v(" "),s("ol",[s("li",[t._v("合約建立時在 "),s("code",[t._v("constructor")]),t._v(" 階段,將 owner 設定成 "),s("code",[t._v("msg.sender")]),t._v("。")]),t._v(" "),s("li",[t._v("提供了 "),s("code",[t._v("OwnershipTransferred")]),t._v(" 的事件,當合約的擁有者轉移時觸發。")]),t._v(" "),s("li",[t._v("提供 "),s("code",[t._v("owner")]),t._v(" 函式用來查詢當前的擁有者。")]),t._v(" "),s("li",[t._v("提供 "),s("code",[t._v("onlyOwner")]),t._v(" 的修飾子,方便套用在函式上,用來限制只允許擁有者存取的函式。")]),t._v(" "),s("li",[t._v("提供 "),s("code",[t._v("renounceOwnership")]),t._v(" 函式,將擁有者設定為位址 "),s("code",[t._v("0")]),t._v(" ,其涵義為讓這個合約永久變成無擁有者狀態。")]),t._v(" "),s("li",[t._v("提供 "),s("code",[t._v("transferOwnership")]),t._v(" 函式,用來轉移擁有者。")])]),t._v(" "),s("p",[t._v("值得一提的是,為了較佳的可讀性,與避免重複的程式碼出現,我們可以發現所有設定 "),s("code",[t._v("owner")]),t._v(" 的操作都是透過呼叫一個特別的內部函式 "),s("code",[t._v("_setOwner")]),t._v("。")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SPDX-License-Identifier: MIT")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"../utils/Context.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */")]),t._v("\nabstract "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("contract")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ownable")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Context "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("event")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("OwnershipTransferred")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("indexed")]),t._v(" previousOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("indexed")]),t._v(" newOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_setOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Returns the address of the current owner.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("owner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Throws if called by any account other than the owner.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("modifier")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("onlyOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("owner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Ownable: caller is not the owner"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("_")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("renounceOwnership")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" virtual onlyOwner "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_setOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transferOwnership")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" newOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" virtual onlyOwner "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("newOwner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Ownable: new owner is the zero address"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_setOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("newOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_setOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" newOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" oldOwner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n _owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" newOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("OwnershipTransferred")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("oldOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" newOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h3",{attrs:{id:"reentrancyguard-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#reentrancyguard-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("ReentrancyGuard.sol")])]),t._v(" "),s("p",[s("code",[t._v("ReentrancyGuard")]),t._v(" 是一個輔助合約,用來規避重入攻擊(reentrant attack)。")]),t._v(" "),s("ol",[s("li",[t._v("合約提供一個修飾子 "),s("code",[t._v("nonReentrant")]),t._v(" 用來避免同一個函式被直接或間接地重複呼叫,以規避重入攻擊。")])]),t._v(" "),s("p",[t._v("推薦一部"),s("a",{attrs:{href:"https://www.youtube.com/watch?v=76So4jCysAQ",target:"_blank",rel:"noopener noreferrer"}},[t._v("影片"),s("OutboundLink")],1),t._v(",裡頭舉例了一個重入攻擊怎麼發生,以及如何避免。")]),t._v(" "),s("p",[t._v("值得注意的是,該合約在註解中提到:「使用 boolean 會比 uint256 還昂貴」,理由是因為以太坊虛擬機中的每個記憶體單元的長度跟 uint256 一樣大,然而使用 boolean 來儲存狀態的話,會因為他需要「讀出 uint256 的長度,然後只修改最尾端的位元」,因此會使對 boolean 的操作更貴。")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SPDX-License-Identifier: MIT")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */")]),t._v("\nabstract "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("contract")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ReentrancyGuard")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Booleans are more expensive than uint256 or any type that takes up a full")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// word because each write operation emits an extra SLOAD to first read the")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// slot's contents, replace the bits taken up by the boolean, and then write")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// back. This is the compiler's defense against contract upgrades and")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// pointer aliasing, and it cannot be disabled.")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The values being non-zero value makes deployment a bit more expensive,")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// but in exchange the refund on every call to nonReentrant will be lower in")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// amount. Since refunds are capped to a percentage of the total")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// transaction's gas, it is best to keep them low in cases like this one, to")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// increase the likelihood of the full refund coming into effect.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" _NOT_ENTERED "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" _ENTERED "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _status"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n _status "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _NOT_ENTERED"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and make it call a\n * `private` function that does the actual work.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("modifier")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("nonReentrant")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// On the first call to nonReentrant, _notEntered will be true")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_status "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" _ENTERED"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ReentrancyGuard: reentrant call"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Any calls to nonReentrant after this point will fail")]),t._v("\n _status "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _ENTERED"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("_")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// By storing the original value once again, a refund is triggered (see")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// https://eips.ethereum.org/EIPS/eip-2200)")]),t._v("\n _status "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _NOT_ENTERED"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[47],{368:function(t,s,n){"use strict";n.r(s);var a=n(17),e=Object(a.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"實例解析-proof-of-stake-書籍的捐款合約-part-3"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#實例解析-proof-of-stake-書籍的捐款合約-part-3"}},[t._v("#")]),t._v(" 實例解析 - Proof of Stake 書籍的捐款合約 Part 3")]),t._v(" "),s("h2",{attrs:{id:"合約原始碼"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#合約原始碼"}},[t._v("#")]),t._v(" 合約原始碼")]),t._v(" "),s("p",[s("a",{attrs:{href:"https://etherscan.io/address/0x5bf5bcc5362f88721167c1068b58c60cad075aac#code",target:"_blank",rel:"noopener noreferrer"}},[t._v("合約原始碼請點此"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"proofofstake-pages-sol-引用的函式庫與介面"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#proofofstake-pages-sol-引用的函式庫與介面"}},[t._v("#")]),t._v(" "),s("code",[t._v("ProofOfStake_Pages.sol")]),t._v(" 引用的函式庫與介面")]),t._v(" "),s("p",[t._v("ProofOfStake_Pages 合約中引入的函式庫與介面,可以看到以下的結構("),s("code",[t._v("*")]),t._v(" 為本日說明的範圍)")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[t._v("ProofOfStake_Pages\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Ownable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ReentrancyGuard"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721Receiver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721Metadata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" Address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Counters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n")])])]),s("h3",{attrs:{id:"ownable-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#ownable-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("Ownable.sol")])]),t._v(" "),s("p",[s("code",[t._v("Ownable")]),t._v(" 是一個輔助合約,讓繼承的合約可以擁有對合約的存取管理權限,它提供了以下功能:")]),t._v(" "),s("ol",[s("li",[t._v("合約建立時在 "),s("code",[t._v("constructor")]),t._v(" 階段,將 owner 設定成 "),s("code",[t._v("msg.sender")]),t._v("。")]),t._v(" "),s("li",[t._v("提供了 "),s("code",[t._v("OwnershipTransferred")]),t._v(" 的事件,當合約的擁有者轉移時觸發。")]),t._v(" "),s("li",[t._v("提供 "),s("code",[t._v("owner")]),t._v(" 函式用來查詢當前的擁有者。")]),t._v(" "),s("li",[t._v("提供 "),s("code",[t._v("onlyOwner")]),t._v(" 的修飾子,方便套用在函式上,用來限制只允許擁有者存取的函式。")]),t._v(" "),s("li",[t._v("提供 "),s("code",[t._v("renounceOwnership")]),t._v(" 函式,將擁有者設定為位址 "),s("code",[t._v("0")]),t._v(" ,其涵義為讓這個合約永久變成無擁有者狀態。")]),t._v(" "),s("li",[t._v("提供 "),s("code",[t._v("transferOwnership")]),t._v(" 函式,用來轉移擁有者。")])]),t._v(" "),s("p",[t._v("值得一提的是,為了較佳的可讀性,與避免重複的程式碼出現,我們可以發現所有設定 "),s("code",[t._v("owner")]),t._v(" 的操作都是透過呼叫一個特別的內部函式 "),s("code",[t._v("_setOwner")]),t._v("。")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SPDX-License-Identifier: MIT")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"../utils/Context.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */")]),t._v("\nabstract "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("contract")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ownable")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Context "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("event")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("OwnershipTransferred")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("indexed")]),t._v(" previousOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("indexed")]),t._v(" newOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_setOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Returns the address of the current owner.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("owner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Throws if called by any account other than the owner.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("modifier")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("onlyOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("owner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Ownable: caller is not the owner"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("_")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("renounceOwnership")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" virtual onlyOwner "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_setOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transferOwnership")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" newOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" virtual onlyOwner "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("newOwner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Ownable: new owner is the zero address"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_setOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("newOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_setOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" newOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" oldOwner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n _owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" newOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("OwnershipTransferred")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("oldOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" newOwner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h3",{attrs:{id:"reentrancyguard-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#reentrancyguard-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("ReentrancyGuard.sol")])]),t._v(" "),s("p",[s("code",[t._v("ReentrancyGuard")]),t._v(" 是一個輔助合約,用來規避重入攻擊(reentrant attack)。")]),t._v(" "),s("ol",[s("li",[t._v("合約提供一個修飾子 "),s("code",[t._v("nonReentrant")]),t._v(" 用來避免同一個函式被直接或間接地重複呼叫,以規避重入攻擊。")])]),t._v(" "),s("p",[t._v("推薦一部"),s("a",{attrs:{href:"https://www.youtube.com/watch?v=76So4jCysAQ",target:"_blank",rel:"noopener noreferrer"}},[t._v("影片"),s("OutboundLink")],1),t._v(",裡頭舉例了一個重入攻擊怎麼發生,以及如何避免。")]),t._v(" "),s("p",[t._v("值得注意的是,該合約在註解中提到:「使用 boolean 會比 uint256 還昂貴」,理由是因為以太坊虛擬機中的每個記憶體單元的長度跟 uint256 一樣大,然而使用 boolean 來儲存狀態的話,會因為他需要「讀出 uint256 的長度,然後只修改最尾端的位元」,因此會使對 boolean 的操作更貴。")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SPDX-License-Identifier: MIT")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */")]),t._v("\nabstract "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("contract")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ReentrancyGuard")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Booleans are more expensive than uint256 or any type that takes up a full")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// word because each write operation emits an extra SLOAD to first read the")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// slot's contents, replace the bits taken up by the boolean, and then write")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// back. This is the compiler's defense against contract upgrades and")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// pointer aliasing, and it cannot be disabled.")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The values being non-zero value makes deployment a bit more expensive,")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// but in exchange the refund on every call to nonReentrant will be lower in")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// amount. Since refunds are capped to a percentage of the total")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// transaction's gas, it is best to keep them low in cases like this one, to")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// increase the likelihood of the full refund coming into effect.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" _NOT_ENTERED "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" _ENTERED "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _status"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n _status "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _NOT_ENTERED"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and make it call a\n * `private` function that does the actual work.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("modifier")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("nonReentrant")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// On the first call to nonReentrant, _notEntered will be true")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_status "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" _ENTERED"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ReentrancyGuard: reentrant call"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Any calls to nonReentrant after this point will fail")]),t._v("\n _status "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _ENTERED"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("_")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// By storing the original value once again, a refund is triggered (see")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// https://eips.ethereum.org/EIPS/eip-2200)")]),t._v("\n _status "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _NOT_ENTERED"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/50.43fa6b01.js b/assets/js/50.b054b2ac.js similarity index 99% rename from assets/js/50.43fa6b01.js rename to assets/js/50.b054b2ac.js index 96d6411..4eaaf29 100644 --- a/assets/js/50.43fa6b01.js +++ b/assets/js/50.b054b2ac.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[50],{373:function(t,s,n){"use strict";n.r(s);var a=n(17),e=Object(a.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"實例解析-proof-of-stake-書籍的捐款合約-part-6"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#實例解析-proof-of-stake-書籍的捐款合約-part-6"}},[t._v("#")]),t._v(" 實例解析 - Proof of Stake 書籍的捐款合約 Part 6")]),t._v(" "),s("h2",{attrs:{id:"合約原始碼"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#合約原始碼"}},[t._v("#")]),t._v(" 合約原始碼")]),t._v(" "),s("p",[s("a",{attrs:{href:"https://etherscan.io/address/0x5bf5bcc5362f88721167c1068b58c60cad075aac#code",target:"_blank",rel:"noopener noreferrer"}},[t._v("合約原始碼請點此"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"proofofstake-pages-sol-引用的函式庫與介面"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#proofofstake-pages-sol-引用的函式庫與介面"}},[t._v("#")]),t._v(" "),s("code",[t._v("ProofOfStake_Pages.sol")]),t._v(" 引用的函式庫與介面")]),t._v(" "),s("p",[t._v("ProofOfStake_Pages 合約中引入的函式庫與介面,可以看到以下的結構("),s("code",[t._v("*")]),t._v(" 為本日說明的範圍)")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[t._v("ProofOfStake_Pages\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Ownable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ReentrancyGuard"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721Receiver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721Metadata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Counters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n")])])]),s("h3",{attrs:{id:"erc721-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#erc721-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("ERC721.sol")])]),t._v(" "),s("p",[t._v("基本上這邊的 ERC721 就是標準實作。\n請大家直接參考下面的程式碼,我把加上了中文註解方便理解內容。")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SPDX-License-Identifier: MIT")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"./IERC721.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"./IERC721Receiver.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"./extensions/IERC721Metadata.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"../../utils/Address.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"../../utils/Context.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"../../utils/Strings.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"../../utils/introspection/ERC165.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("contract")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ERC721")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IERC721Metadata "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("using")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("using")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Strings")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 代幣名稱")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Token name")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 代幣簡稱")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Token symbol")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _symbol"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 用來儲存 token ID 對 擁有者位址的映射結構")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Mapping from token ID to owner address")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _owners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 用來儲存 擁有者位址 對 token 持有數量的映射結構")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Mapping owner address to token count")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _balances"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 用來儲存 token ID 對 被授權者位址的映射結構")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Mapping from token ID to approved address")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _tokenApprovals"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 用來儲存 持有者 對 第三方授權 的映射結構")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Mapping from owner to operator approvals")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _operatorApprovals"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 建構子,初始化 ERC721 的名稱與簡稱")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" name_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" symbol_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n _name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" name_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n _symbol "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" symbol_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 告訴使用者,本合約支援: IERC721, IERC721Metadata 與 IERC165")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC165-supportsInterface}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("supportsInterface")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes4")]),t._v(" interfaceId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("override")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n interfaceId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("type")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interfaceId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v("\n interfaceId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("type")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("IERC721Metadata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interfaceId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v("\n super"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("supportsInterface")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("interfaceId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳持有者持有數量")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-balanceOf}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("balanceOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// address 0 不能是持有者")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: balance query for the zero address"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _balances"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳該 token ID 的持有者")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-ownerOf}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ownerOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取出持有者資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _owners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查持有者必不能是 address 0")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: owner query for nonexistent token"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳名稱")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721Metadata-name}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("name")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳簡稱")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721Metadata-symbol}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("symbol")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _symbol"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳該 token ID 的 URI 資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721Metadata-tokenURI}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("tokenURI")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// URI 只對還存在的 token ID 有意義")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_exists")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721Metadata: URI query for nonexistent token"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取得基礎 URI (ipfs:// or http://example...)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" baseURI "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_baseURI")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 組合成完整的 URI,通常是基礎 URI + tokenID 為該 token 的完整 URI 資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("baseURI"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("baseURI"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳基礎 URI")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overriden in child contracts.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_baseURI")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 預設為無")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 授權函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-approve}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("approve")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取得持有者資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ownerOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 持有者不能授權給自己")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: approval to current owner"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫者必須是:")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1. 持有者本人")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2. 擁有持有者授權的第三方位址")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isApprovedForAll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: approve caller is not owner nor approved for all"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫內部函式進行授權")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_approve")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳該 token ID 的被授權者")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-getApproved}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getApproved")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 只有存在的 token ID 才能有被授權者")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_exists")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: approved query for nonexistent token"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _tokenApprovals"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 授權/撤銷名下全部的 NFT 給第三方位址")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-setApprovalForAll}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("setApprovalForAll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" operator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" approved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 持有者不能授權給自己")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("operator "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: approve to caller"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 設定授權/撤銷")]),t._v("\n _operatorApprovals"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("operator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" approved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 觸發授權事件")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ApprovalForAll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" operator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" approved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳持有者是否授權給特定第三方位址")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-isApprovedForAll}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isApprovedForAll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" operator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _operatorApprovals"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("operator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 轉移函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-transferFrom}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transferFrom")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查呼叫者是否有權轉移此代幣")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//solhint-disable-next-line max-line-length")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_isApprovedOrOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: transfer caller is not owner nor approved"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫內部轉移函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_transfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 安全轉移函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-safeTransferFrom}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("safeTransferFrom")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 直接呼叫帶有 data 欄位的版本")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("safeTransferFrom")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 安全轉移函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-safeTransferFrom}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("safeTransferFrom")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" _data\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查呼叫者是否有權進行轉移")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_isApprovedOrOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: transfer caller is not owner nor approved"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫內部安全轉移函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_safeTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部的安全轉移函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * `_data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_safeTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" _data\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫內部轉移函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_transfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查接收者是否為合約,以及是否正確實作 IERC721Receiver")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_checkOnERC721Received")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: transfer to non ERC721Receiver implementer"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,檢查 token ID 是否存在")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_exists")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 只有當持有者非 address 0 時才算存在。若持有者為 address 0 ,則不是已經被銷毀,就是還沒被鑄造")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _owners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,回傳被查詢者是否擁有對 token ID 代幣的管理權:")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1. 被查詢者為持有者本人 => true")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2. 被查詢者擁有持有者的授權")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_isApprovedOrOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" spender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 只有存在的 token ID 才有檢查的必要")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_exists")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: operator query for nonexistent token"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取出持有者資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ownerOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 當以下其中一個條件滿足時,則代表擁有管理權:")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1. 持有者本人")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2. 擁有對該 token ID 的管理權")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 3. 擁有對該持有者名下全部 token 的管理權")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("spender "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getApproved")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" spender "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isApprovedForAll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" spender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,安全地鑄造代幣")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_safeMint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫帶有 data 欄位的版本")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_safeMint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,安全鑄造函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_safeMint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" _data\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫內部鑄造函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_mint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查接收方若為合約,則必須實作 IERC721Received 介面")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_checkOnERC721Received")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: transfer to non ERC721Receiver implementer"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,鑄造代幣")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 鑄造其實就是無中生有,將一個代幣從 address 0 轉移出來")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_mint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 接收者不能為 address 0 (等同銷毀)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: mint to the zero address"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 被鑄造的代幣不能重複")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_exists")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: token already minted"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫轉移前的 hook")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 增加接收者的持有數量")]),t._v("\n _balances"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 設定該 token 的持有者")]),t._v("\n _owners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 觸發轉移事件")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Transfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,銷毀代幣")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_burn")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取得持有者資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ownerOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 執行轉移前的 hook")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 清空授權")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Clear approvals")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_approve")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 減少持有者的持有數量")]),t._v("\n _balances"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 清空該代幣的持有者資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("delete")]),t._v(" _owners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 觸發轉移事件")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Transfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,用來進行轉移")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_transfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查 from 為 tokenId 的持有者")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ownerOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: transfer of token that is not own"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查 to 不可為 address 0")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: transfer to the zero address"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 執行轉移前的 hook")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將 tokenId 的授權者設定為 address 0 (清空授權)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Clear approvals from the previous owner")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_approve")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 減少原持有者的持有數量")]),t._v("\n _balances"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 增加接收者的持有數量")]),t._v("\n _balances"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將接收者設定為新的持有者")]),t._v("\n _owners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 觸發轉移事件")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Transfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,用來進行授權")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits a {Approval} event.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_approve")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將 tokenId 授權給 to")]),t._v("\n _tokenApprovals"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 觸發授權事件")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Approval")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ownerOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,專門用來檢查接收方是否為合約,若是,則需要正確實作 IERC721Receiver.onERC721Received,否則就觸發錯誤或回傳 false")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param _data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_checkOnERC721Received")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" _data\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查接收者是否為合約")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isContract")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 嘗試呼叫 IERC721Receiver 的介面,以檢查實作是否正確")]),t._v("\n try "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("IERC721Receiver")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("onERC721Received")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes4")]),t._v(" retval"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" retval "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" IERC721Receiver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("onERC721Received"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("selector"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" catch "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" reason"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 若發生錯誤,則顯示出錯誤的理由")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reason"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: transfer to non ERC721Receiver implementer"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("assembly")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" reason"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mload")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reason"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 在轉移任何代幣之前的 hook,也就是會先執行它,再進行代幣轉移。")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h3",{attrs:{id:"erc721enumerable-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#erc721enumerable-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("ERC721Enumerable.sol")])]),t._v(" "),s("p",[t._v("這個是對 ERC721 的擴充介面。")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SPDX-License-Identifier: MIT")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"../ERC721.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"./IERC721Enumerable.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev This implements an optional extension of {ERC721} defined in the EIP that adds\n * enumerability of all the token ids in the contract as well as all token ids owned by each\n * account.\n */")]),t._v("\nabstract "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("contract")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ERC721Enumerable")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IERC721Enumerable "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 儲存持有者 對 其名下代幣列表 的映射結構")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Mapping from owner to list of owned token IDs")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _ownedTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 儲存 token ID 對 其在持有者名下序號 的映射結構")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Mapping from token ID to index of the owner tokens list")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _ownedTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 儲存所有 token id 的陣列,用來列舉全部代幣所用")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Array with all token ids, used for enumeration")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 儲存 token id 到 其在 `_allTokens` 陣列中的位置")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Mapping from token id to position in the allTokens array")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _allTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查支援的介面")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC165-supportsInterface}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("supportsInterface")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes4")]),t._v(" interfaceId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("override")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 支援 IERC721Enumerable 或被此合約繼承的介面")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" interfaceId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("type")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("IERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interfaceId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" super"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("supportsInterface")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("interfaceId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 利用持有者資訊與該代幣在持有者列表中的序號,來反查代幣編號")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("tokenOfOwnerByIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" index"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 序號必定小於持有者的持有總數")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("index "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("balanceOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721Enumerable: owner index out of bounds"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _ownedTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("index"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳目前鑄造出的代幣總量")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721Enumerable-totalSupply}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("totalSupply")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳在所有代幣中,序號為 index 的代幣編號 ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721Enumerable-tokenByIndex}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("tokenByIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" index"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 查詢的序號必須低於鑄造出的代幣總量")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("index "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" ERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("totalSupply")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721Enumerable: global index out of bounds"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("index"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 在轉移前的 hook")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n super"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n \n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 若為鑄造所觸發的轉移 */")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將新代幣加入總代幣列表")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_addTokenToAllTokensEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" to "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 原持有者轉移代幣 */")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將代幣從原持有者列表中移除")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_removeTokenFromOwnerEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 若為銷毀所觸發的轉移 */")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將代幣從總代幣列表中移除")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_removeTokenFromAllTokensEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 新持有者接收代幣 */")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將代幣加入新持有者列表中")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_addTokenToOwnerEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,用來將代幣加入新持有者列表中")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Private function to add a token to this extension's ownership-tracking data structures.\n * @param to address representing the new owner of the given token ID\n * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_addTokenToOwnerEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取得新持有者的持有總數")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("balanceOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將新代幣加入持有列表的尾端")]),t._v("\n _ownedTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("length"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將新代幣的序號設定為持有列表的當前長度")]),t._v("\n _ownedTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" length"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,用來將新代幣加入總代幣列表中")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Private function to add a token to this extension's token tracking data structures.\n * @param tokenId uint256 ID of the token to be added to the tokens list\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_addTokenToAllTokensEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 更新序號")]),t._v("\n _allTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 加入總代幣列表")]),t._v("\n _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,從原持有者列表中移除代幣")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\n * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\n * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\n * This has O(1) time complexity, but alters the order of the _ownedTokens array.\n * @param from address representing the previous owner of the given token ID\n * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_removeTokenFromOwnerEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 為了避免在持有者列表中產生空位,總會利用交換的方式,把想移除的代幣換到最後一個代幣的欄位,再行移除")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// then delete the last slot (swap and pop).")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取得最後代幣的序號")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" lastTokenIndex "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("balanceOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取得目標代幣的序號")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenIndex "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _ownedTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 只有最後代幣與目標代幣的序號不同時,需要進行交換")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// When the token to delete is the last token, the swap operation is unnecessary")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenIndex "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" lastTokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" lastTokenId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _ownedTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("lastTokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n _ownedTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" lastTokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Move the last token to the slot of the to-delete token")]),t._v("\n _ownedTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("lastTokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" tokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Update the moved token's index")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 刪除最後代幣的持有者資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This also deletes the contents at the last position of the array")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("delete")]),t._v(" _ownedTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("delete")]),t._v(" _ownedTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("lastTokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,將代幣從總代幣列表中移除")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Private function to remove a token from this extension's token tracking data structures.\n * This has O(1) time complexity, but alters the order of the _allTokens array.\n * @param tokenId uint256 ID of the token to be removed from the tokens list\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_removeTokenFromAllTokensEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 為了避免總代幣列表中產生空位,因此會採用交換目標代幣列表的最尾端,再行刪除。")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// then delete the last slot (swap and pop).")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" lastTokenIndex "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenIndex "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _allTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// an 'if' statement (like in _removeTokenFromOwnerEnumeration)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" lastTokenId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("lastTokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" lastTokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Move the last token to the slot of the to-delete token")]),t._v("\n _allTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("lastTokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" tokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Update the moved token's index")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This also deletes the contents at the last position of the array")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("delete")]),t._v(" _allTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pop")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[50],{371:function(t,s,n){"use strict";n.r(s);var a=n(17),e=Object(a.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"實例解析-proof-of-stake-書籍的捐款合約-part-6"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#實例解析-proof-of-stake-書籍的捐款合約-part-6"}},[t._v("#")]),t._v(" 實例解析 - Proof of Stake 書籍的捐款合約 Part 6")]),t._v(" "),s("h2",{attrs:{id:"合約原始碼"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#合約原始碼"}},[t._v("#")]),t._v(" 合約原始碼")]),t._v(" "),s("p",[s("a",{attrs:{href:"https://etherscan.io/address/0x5bf5bcc5362f88721167c1068b58c60cad075aac#code",target:"_blank",rel:"noopener noreferrer"}},[t._v("合約原始碼請點此"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"proofofstake-pages-sol-引用的函式庫與介面"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#proofofstake-pages-sol-引用的函式庫與介面"}},[t._v("#")]),t._v(" "),s("code",[t._v("ProofOfStake_Pages.sol")]),t._v(" 引用的函式庫與介面")]),t._v(" "),s("p",[t._v("ProofOfStake_Pages 合約中引入的函式庫與介面,可以看到以下的結構("),s("code",[t._v("*")]),t._v(" 為本日說明的範圍)")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[t._v("ProofOfStake_Pages\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Ownable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ReentrancyGuard"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721Receiver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721Metadata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Counters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n")])])]),s("h3",{attrs:{id:"erc721-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#erc721-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("ERC721.sol")])]),t._v(" "),s("p",[t._v("基本上這邊的 ERC721 就是標準實作。\n請大家直接參考下面的程式碼,我把加上了中文註解方便理解內容。")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SPDX-License-Identifier: MIT")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"./IERC721.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"./IERC721Receiver.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"./extensions/IERC721Metadata.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"../../utils/Address.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"../../utils/Context.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"../../utils/Strings.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"../../utils/introspection/ERC165.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("contract")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ERC721")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IERC721Metadata "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("using")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("using")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Strings")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 代幣名稱")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Token name")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 代幣簡稱")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Token symbol")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _symbol"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 用來儲存 token ID 對 擁有者位址的映射結構")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Mapping from token ID to owner address")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _owners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 用來儲存 擁有者位址 對 token 持有數量的映射結構")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Mapping owner address to token count")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _balances"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 用來儲存 token ID 對 被授權者位址的映射結構")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Mapping from token ID to approved address")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _tokenApprovals"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 用來儲存 持有者 對 第三方授權 的映射結構")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Mapping from owner to operator approvals")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _operatorApprovals"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 建構子,初始化 ERC721 的名稱與簡稱")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" name_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" symbol_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n _name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" name_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n _symbol "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" symbol_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 告訴使用者,本合約支援: IERC721, IERC721Metadata 與 IERC165")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC165-supportsInterface}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("supportsInterface")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes4")]),t._v(" interfaceId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("override")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n interfaceId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("type")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interfaceId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v("\n interfaceId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("type")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("IERC721Metadata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interfaceId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v("\n super"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("supportsInterface")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("interfaceId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳持有者持有數量")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-balanceOf}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("balanceOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// address 0 不能是持有者")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: balance query for the zero address"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _balances"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳該 token ID 的持有者")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-ownerOf}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ownerOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取出持有者資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _owners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查持有者必不能是 address 0")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: owner query for nonexistent token"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳名稱")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721Metadata-name}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("name")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳簡稱")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721Metadata-symbol}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("symbol")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _symbol"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳該 token ID 的 URI 資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721Metadata-tokenURI}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("tokenURI")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// URI 只對還存在的 token ID 有意義")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_exists")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721Metadata: URI query for nonexistent token"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取得基礎 URI (ipfs:// or http://example...)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" baseURI "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_baseURI")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 組合成完整的 URI,通常是基礎 URI + tokenID 為該 token 的完整 URI 資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("baseURI"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("baseURI"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳基礎 URI")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overriden in child contracts.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_baseURI")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 預設為無")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 授權函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-approve}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("approve")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取得持有者資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ownerOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 持有者不能授權給自己")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: approval to current owner"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫者必須是:")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1. 持有者本人")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2. 擁有持有者授權的第三方位址")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isApprovedForAll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: approve caller is not owner nor approved for all"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫內部函式進行授權")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_approve")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳該 token ID 的被授權者")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-getApproved}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getApproved")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 只有存在的 token ID 才能有被授權者")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_exists")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: approved query for nonexistent token"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _tokenApprovals"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 授權/撤銷名下全部的 NFT 給第三方位址")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-setApprovalForAll}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("setApprovalForAll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" operator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" approved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 持有者不能授權給自己")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("operator "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: approve to caller"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 設定授權/撤銷")]),t._v("\n _operatorApprovals"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("operator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" approved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 觸發授權事件")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ApprovalForAll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" operator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" approved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳持有者是否授權給特定第三方位址")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-isApprovedForAll}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isApprovedForAll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" operator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _operatorApprovals"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("operator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 轉移函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-transferFrom}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transferFrom")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查呼叫者是否有權轉移此代幣")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//solhint-disable-next-line max-line-length")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_isApprovedOrOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: transfer caller is not owner nor approved"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫內部轉移函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_transfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 安全轉移函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-safeTransferFrom}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("safeTransferFrom")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 直接呼叫帶有 data 欄位的版本")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("safeTransferFrom")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 安全轉移函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721-safeTransferFrom}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("safeTransferFrom")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" _data\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查呼叫者是否有權進行轉移")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_isApprovedOrOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: transfer caller is not owner nor approved"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫內部安全轉移函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_safeTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部的安全轉移函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * `_data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_safeTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" _data\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫內部轉移函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_transfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查接收者是否為合約,以及是否正確實作 IERC721Receiver")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_checkOnERC721Received")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: transfer to non ERC721Receiver implementer"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,檢查 token ID 是否存在")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_exists")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 只有當持有者非 address 0 時才算存在。若持有者為 address 0 ,則不是已經被銷毀,就是還沒被鑄造")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _owners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,回傳被查詢者是否擁有對 token ID 代幣的管理權:")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1. 被查詢者為持有者本人 => true")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2. 被查詢者擁有持有者的授權")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_isApprovedOrOwner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" spender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 只有存在的 token ID 才有檢查的必要")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_exists")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: operator query for nonexistent token"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取出持有者資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ownerOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 當以下其中一個條件滿足時,則代表擁有管理權:")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1. 持有者本人")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2. 擁有對該 token ID 的管理權")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 3. 擁有對該持有者名下全部 token 的管理權")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("spender "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getApproved")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" spender "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isApprovedForAll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" spender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,安全地鑄造代幣")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_safeMint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫帶有 data 欄位的版本")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_safeMint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,安全鑄造函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_safeMint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" _data\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫內部鑄造函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_mint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查接收方若為合約,則必須實作 IERC721Received 介面")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_checkOnERC721Received")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: transfer to non ERC721Receiver implementer"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,鑄造代幣")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 鑄造其實就是無中生有,將一個代幣從 address 0 轉移出來")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_mint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 接收者不能為 address 0 (等同銷毀)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: mint to the zero address"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 被鑄造的代幣不能重複")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_exists")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: token already minted"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 呼叫轉移前的 hook")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 增加接收者的持有數量")]),t._v("\n _balances"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 設定該 token 的持有者")]),t._v("\n _owners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 觸發轉移事件")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Transfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,銷毀代幣")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_burn")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取得持有者資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" owner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ownerOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 執行轉移前的 hook")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 清空授權")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Clear approvals")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_approve")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 減少持有者的持有數量")]),t._v("\n _balances"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 清空該代幣的持有者資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("delete")]),t._v(" _owners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 觸發轉移事件")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Transfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,用來進行轉移")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_transfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查 from 為 tokenId 的持有者")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ownerOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: transfer of token that is not own"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查 to 不可為 address 0")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: transfer to the zero address"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 執行轉移前的 hook")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將 tokenId 的授權者設定為 address 0 (清空授權)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Clear approvals from the previous owner")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_approve")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 減少原持有者的持有數量")]),t._v("\n _balances"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 增加接收者的持有數量")]),t._v("\n _balances"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將接收者設定為新的持有者")]),t._v("\n _owners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 觸發轉移事件")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Transfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,用來進行授權")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits a {Approval} event.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_approve")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將 tokenId 授權給 to")]),t._v("\n _tokenApprovals"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 觸發授權事件")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Approval")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ownerOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,專門用來檢查接收方是否為合約,若是,則需要正確實作 IERC721Receiver.onERC721Received,否則就觸發錯誤或回傳 false")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param _data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_checkOnERC721Received")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" _data\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查接收者是否為合約")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isContract")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 嘗試呼叫 IERC721Receiver 的介面,以檢查實作是否正確")]),t._v("\n try "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("IERC721Receiver")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("onERC721Received")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_msgSender")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes4")]),t._v(" retval"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" retval "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" IERC721Receiver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("onERC721Received"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("selector"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" catch "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" reason"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 若發生錯誤,則顯示出錯誤的理由")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reason"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721: transfer to non ERC721Receiver implementer"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("assembly")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" reason"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mload")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reason"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 在轉移任何代幣之前的 hook,也就是會先執行它,再進行代幣轉移。")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h3",{attrs:{id:"erc721enumerable-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#erc721enumerable-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("ERC721Enumerable.sol")])]),t._v(" "),s("p",[t._v("這個是對 ERC721 的擴充介面。")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SPDX-License-Identifier: MIT")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"../ERC721.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"./IERC721Enumerable.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev This implements an optional extension of {ERC721} defined in the EIP that adds\n * enumerability of all the token ids in the contract as well as all token ids owned by each\n * account.\n */")]),t._v("\nabstract "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("contract")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ERC721Enumerable")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IERC721Enumerable "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 儲存持有者 對 其名下代幣列表 的映射結構")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Mapping from owner to list of owned token IDs")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _ownedTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 儲存 token ID 對 其在持有者名下序號 的映射結構")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Mapping from token ID to index of the owner tokens list")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _ownedTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 儲存所有 token id 的陣列,用來列舉全部代幣所用")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Array with all token ids, used for enumeration")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 儲存 token id 到 其在 `_allTokens` 陣列中的位置")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Mapping from token id to position in the allTokens array")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _allTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 檢查支援的介面")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC165-supportsInterface}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("supportsInterface")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes4")]),t._v(" interfaceId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("override")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 支援 IERC721Enumerable 或被此合約繼承的介面")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" interfaceId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("type")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("IERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("interfaceId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" super"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("supportsInterface")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("interfaceId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 利用持有者資訊與該代幣在持有者列表中的序號,來反查代幣編號")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("tokenOfOwnerByIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" index"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 序號必定小於持有者的持有總數")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("index "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("balanceOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721Enumerable: owner index out of bounds"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _ownedTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("owner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("index"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳目前鑄造出的代幣總量")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721Enumerable-totalSupply}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("totalSupply")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 回傳在所有代幣中,序號為 index 的代幣編號 ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev See {IERC721Enumerable-tokenByIndex}.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("tokenByIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" index"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 查詢的序號必須低於鑄造出的代幣總量")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("index "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" ERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("totalSupply")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERC721Enumerable: global index out of bounds"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("index"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 在轉移前的 hook")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual override "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n super"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n \n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 若為鑄造所觸發的轉移 */")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將新代幣加入總代幣列表")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_addTokenToAllTokensEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" to "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 原持有者轉移代幣 */")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將代幣從原持有者列表中移除")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_removeTokenFromOwnerEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 若為銷毀所觸發的轉移 */")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將代幣從總代幣列表中移除")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_removeTokenFromAllTokensEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 新持有者接收代幣 */")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將代幣加入新持有者列表中")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_addTokenToOwnerEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,用來將代幣加入新持有者列表中")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Private function to add a token to this extension's ownership-tracking data structures.\n * @param to address representing the new owner of the given token ID\n * @param tokenId uint256 ID of the token to be added to the tokens list of the given address\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_addTokenToOwnerEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取得新持有者的持有總數")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("balanceOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將新代幣加入持有列表的尾端")]),t._v("\n _ownedTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("length"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將新代幣的序號設定為持有列表的當前長度")]),t._v("\n _ownedTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" length"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,用來將新代幣加入總代幣列表中")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Private function to add a token to this extension's token tracking data structures.\n * @param tokenId uint256 ID of the token to be added to the tokens list\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_addTokenToAllTokensEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 更新序號")]),t._v("\n _allTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 加入總代幣列表")]),t._v("\n _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,從原持有者列表中移除代幣")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that\n * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for\n * gas optimizations e.g. when performing a transfer operation (avoiding double writes).\n * This has O(1) time complexity, but alters the order of the _ownedTokens array.\n * @param from address representing the previous owner of the given token ID\n * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_removeTokenFromOwnerEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 為了避免在持有者列表中產生空位,總會利用交換的方式,把想移除的代幣換到最後一個代幣的欄位,再行移除")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// then delete the last slot (swap and pop).")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取得最後代幣的序號")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" lastTokenIndex "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("balanceOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取得目標代幣的序號")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenIndex "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _ownedTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 只有最後代幣與目標代幣的序號不同時,需要進行交換")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// When the token to delete is the last token, the swap operation is unnecessary")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokenIndex "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" lastTokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" lastTokenId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _ownedTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("lastTokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n _ownedTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" lastTokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Move the last token to the slot of the to-delete token")]),t._v("\n _ownedTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("lastTokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" tokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Update the moved token's index")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 刪除最後代幣的持有者資訊")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This also deletes the contents at the last position of the array")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("delete")]),t._v(" _ownedTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("delete")]),t._v(" _ownedTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("lastTokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 內部函式,將代幣從總代幣列表中移除")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Private function to remove a token from this extension's token tracking data structures.\n * This has O(1) time complexity, but alters the order of the _allTokens array.\n * @param tokenId uint256 ID of the token to be removed from the tokens list\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_removeTokenFromAllTokensEnumeration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 為了避免總代幣列表中產生空位,因此會採用交換目標代幣列表的最尾端,再行刪除。")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// then delete the last slot (swap and pop).")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" lastTokenIndex "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenIndex "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _allTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// an 'if' statement (like in _removeTokenFromOwnerEnumeration)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" lastTokenId "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("lastTokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" lastTokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Move the last token to the slot of the to-delete token")]),t._v("\n _allTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("lastTokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" tokenIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Update the moved token's index")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This also deletes the contents at the last position of the array")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("delete")]),t._v(" _allTokensIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n _allTokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pop")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/51.e45a8c2a.js b/assets/js/51.a77781e8.js similarity index 99% rename from assets/js/51.e45a8c2a.js rename to assets/js/51.a77781e8.js index 33515b7..f997d26 100644 --- a/assets/js/51.e45a8c2a.js +++ b/assets/js/51.a77781e8.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[51],{371:function(t,s,n){"use strict";n.r(s);var a=n(17),e=Object(a.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"實例解析-proof-of-stake-書籍的捐款合約-part-7-final"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#實例解析-proof-of-stake-書籍的捐款合約-part-7-final"}},[t._v("#")]),t._v(" 實例解析 - Proof of Stake 書籍的捐款合約 Part 7 (final)")]),t._v(" "),s("h2",{attrs:{id:"合約原始碼"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#合約原始碼"}},[t._v("#")]),t._v(" 合約原始碼")]),t._v(" "),s("p",[s("a",{attrs:{href:"https://etherscan.io/address/0x5bf5bcc5362f88721167c1068b58c60cad075aac#code",target:"_blank",rel:"noopener noreferrer"}},[t._v("合約原始碼請點此"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"proofofstake-pages-sol-引用的函式庫與介面"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#proofofstake-pages-sol-引用的函式庫與介面"}},[t._v("#")]),t._v(" "),s("code",[t._v("ProofOfStake_Pages.sol")]),t._v(" 引用的函式庫與介面")]),t._v(" "),s("p",[t._v("ProofOfStake_Pages 合約中引入的函式庫與介面,可以看到以下的結構("),s("code",[t._v("*")]),t._v(" 為本日說明的範圍)")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[t._v("ProofOfStake_Pages"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Ownable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ReentrancyGuard"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721Receiver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721Metadata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Counters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n")])])]),s("h3",{attrs:{id:"主菜-proofofstake-pages-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#主菜-proofofstake-pages-sol"}},[t._v("#")]),t._v(" 主菜:"),s("code",[t._v("ProofOfStake_Pages.sol")])]),t._v(" "),s("p",[t._v("這個 NFT 在設計時引入的 Soulbound (靈魂綁定的概念),因此在 NFT 被鑄造出來後,便禁止轉移與授權相關的函式,只有捐款者本人才能持有。")]),t._v(" "),s("p",[t._v("細節請看程式碼註解。")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">=")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.9.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//SPDX-License-Identifier: Apache-2.0")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@openzeppelin/contracts/access/Ownable.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@openzeppelin/contracts/security/ReentrancyGuard.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@openzeppelin/contracts/utils/Strings.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@openzeppelin/contracts/utils/Counters.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("Base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"base64-sol/base64.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"./libs/Transforms.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 宣告錯誤型態")]),t._v("\nerror "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Soulbound")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 靈魂綁定")]),t._v("\nerror "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("PledgingDisabled")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 關閉捐款")]),t._v("\nerror "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("NotMinimumPledge")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 未達最低捐款額度")]),t._v("\nerror "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("SendFailed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 發送失敗")]),t._v("\nerror "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("InvalidSignature")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 不合法的簽名")]),t._v("\nerror "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ZeroSignature")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// address 0 的簽名")]),t._v("\nerror "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("DoesNotExist")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 不存在")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 提供將 addresses 解碼成對應的 ENS 的介面")]),t._v("\nabstract "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("contract")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ENS_Resolver")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getNames")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("calldata")]),t._v(" addresses"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("external")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v("\n virtual\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 本合約繼承了 ERC721Enumerable, Ownable, 與 ReentrancyGuard 三大合約,而他們彼此還有各自的繼承,可以從前幾篇文章找到")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("contract")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ProofOfStake_Pages")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" ERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Ownable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ReentrancyGuard "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n ENS_Resolver res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ENS_Resolver")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x3671aE578E63FdF66ad4F3E12CC0c0d71Ac7510C")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("using")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Counters")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" Counters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("using")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Strings")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*///////////////////////////////////////////////////////////////\n TOKEN STORAGE\n //////////////////////////////////////////////////////////////*/")]),t._v("\n\n Counters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Counter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _tokenIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" pledgeOpen"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// confirm with team")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" price "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.0001337")]),t._v(" ether"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" tokenlimitperuser "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" publisherSplit "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" udonationTotal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//prettier-ignore")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" immutable gitcoin "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xde21F729137C5Af1b01d73aF1dC21eFfa2B8a0d6")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//prettier-ignore")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" immutable sevenStories "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x209D3040C2dEdcb7124be89Fc6849423621EdeaC")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" contractAddressString "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toAsciiString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" currentMessage"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 定義 NFT 的資料結構")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Token")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" recipient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" rAddress"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" sigValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" writtenMsg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n Token"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*///////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("event")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Pledge")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("indexed")]),t._v(" pledgee"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("indexed")]),t._v(" pledgeValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*///////////////////////////////////////////////////////////////\n EIP-712 STORAGE\n //////////////////////////////////////////////////////////////*/")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 寫死 vitalik 的位址")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//prettier-ignore")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" immutable vitalik "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" immutable INITIAL_CHAIN_ID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" immutable INITIAL_DOMAIN_SEPARATOR"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" AUTOGRAPH_TYPEHASH "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"signature(address sender,address recipient,string pledge,string timestamp,string msg)"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*///////////////////////////////////////////////////////////////\n STRUCTOR\n //////////////////////////////////////////////////////////////*/")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 建構子,允許在建構新合約的當下,鑄造已經捐款者的 NFT")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" _donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" _amounts"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ERC721")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Proof Of Stake Pages"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PoSp"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transferOwnership")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xb010ca9Be09C382A9f31b79493bb232bCC319f01")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 設定發行此合約的 chain id 用來驗證簽名")]),t._v("\n INITIAL_CHAIN_ID "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" block"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("chainid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n INITIAL_DOMAIN_SEPARATOR "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("computeDomainSeparator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 發行 NFT 給已經捐款者")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" i "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" _donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("_donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("_donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" resolved "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("resolveENS")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n udonationTotal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("_donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" _amounts"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n _tokenIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("increment")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _tokenIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("current")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_mint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Token")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n recipient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" resolved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n rAddress"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n sigValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _amounts"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" block"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n writtenMsg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Thank you for believing."')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Pledge")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _amounts"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*///////////////////////////////////////////////////////////////\n PLEDGE LOGIC\n //////////////////////////////////////////////////////////////*/")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 捐款(原則上,這個合約的 NFT 是在這邊被鑄造出來的)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('/**\n * @notice Pledges ETH to GTC & "whitelists" pledger\n */')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//prettier-ignore")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pledge")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("payable")]),t._v(" nonReentrant "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 若捐款關閉中,則觸發錯誤")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pledgeOpen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("PledgingDisabled")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 若捐款的錢低於門檻,觸發錯誤")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" price"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("NotMinimumPledge")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" resolved "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("resolveENS")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 計算發行商的分潤")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint")]),t._v(" sShare "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" publisherSplit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 若呼叫者捐款多次,會更新在 NFT 上")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">=")]),t._v(" tokenlimitperuser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 發送部分收入給 gitcoin")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" success3"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" gitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("call"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" sShare"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("success3"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("SendFailed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 發送分潤給發行商 sevenStories")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" success4"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" sevenStories"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("call"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" sShare"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("success4"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("SendFailed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 更新捐款紀錄")]),t._v("\n udonationTotal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 更新捐款次數")]),t._v("\n pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 反之,這是呼叫者的第一次捐款")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 先發送部分收入給 gitcoin")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" success"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" gitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("call"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" sShare"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("success"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("SendFailed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 再發送分潤給發行商 sevenStories")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" success2"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" sevenStories"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("call"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" sShare"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("success2"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("SendFailed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 更新發送者的捐款紀錄")]),t._v("\n udonationTotal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 更新發送者的捐款次數")]),t._v("\n pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 建立新的 token ID")]),t._v("\n _tokenIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("increment")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取得新的 token ID")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _tokenIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("current")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 利用新 ID 來鑄造 NFT 給捐款者")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_mint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將新代幣加入代幣列表中")]),t._v("\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Token")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n recipient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" resolved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 捐款者的 ENS */")]),t._v("\n rAddress"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 捐款者的位址 */")]),t._v("\n sigValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 捐款者的捐款數量 */")]),t._v("\n timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" block"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 捐款當下區塊的時間 */")]),t._v("\n writtenMsg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" currentMessage "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 當前 Vitalik 留下的訊息 */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 觸發捐款事件")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Pledge")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 設定訊息")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 只有 vitalik 才能觸發")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("setMessage")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("calldata")]),t._v(" _message"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("external")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" vitalik"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_message"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("60")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n currentMessage "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _message"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 解析特定位址對應的 ENS ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("resolveENS")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" _user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" resolved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" forCall "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n forCall"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" callres "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getNames")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("forCall"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("callres"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n resolved "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("concat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0x"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toAsciiString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n resolved "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" callres"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" resolved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 更新使用者的 NFT,當本合約收到來自 Vitalik 的合法簽名訊息")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice Updates the user token if we have a valid msg from Vitalik\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//prettier-ignore")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("updateIfSigned")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("calldata")]),t._v(" _signature"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("calldata")]),t._v(" _sigValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("calldata")]),t._v(" _timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("calldata")]),t._v(" _message\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("external")]),t._v(" nonReentrant "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),t._v(" v"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),t._v(" r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),t._v(" s"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("splitSignature")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_signature"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),t._v(" hashStruct "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encode")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n AUTOGRAPH_TYPEHASH"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Will be wockis address in live v")]),t._v("\n vitalik"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Signature will be invalid if it isn't to caller &&")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// EIP712: "Addresses are encoded as uint160"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint160")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// EIP712: "values bytes and string are encoded as a keccak256 hash"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_sigValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_message"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),t._v(" hash "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"\\x19\\x01"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("DOMAIN_SEPARATOR")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" hashStruct"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" signer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ecrecover")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("signer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" vitalik"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("InvalidSignature")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("signer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ZeroSignature")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenid "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("tokenOfOwnerByIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("writtenMsg "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _message"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 切換捐款開關")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice Toggles Pledging On / Off\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("togglePledging")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" onlyOwner "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n pledgeOpen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" pledgeOpen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" pledgeOpen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*///////////////////////////////////////////////////////////////\n TOKEN LOGIC\n //////////////////////////////////////////////////////////////*/")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 由於本合約發出的 NFT 為靈魂綁定代幣,因此封印轉移相關函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice SOULBOUND: Block transfers.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("override")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" to "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"SOULBOUND: Non-Transferable"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n super"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 由於本合約發出的 NFT 為靈魂綁定代幣,因此封印授權相關函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice SOULBOUND: Block approvals.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("setApprovalForAll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" operator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" _approved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v("\n virtual\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("override")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Soulbound")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 由於本合約發出的 NFT 為靈魂綁定代幣,因此封印授權相關函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice SOULBOUND: Block approvals.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("approve")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v("\n virtual\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("override")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Soulbound")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 用來產生 SVG 的函式,只需要留意裡面用到的變數即可")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice Generate SVG using tParams by index\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generateSVG")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" eth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" message"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("writtenMsg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n message "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("concat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n message "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("concat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("writtenMsg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\"'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" eth1 "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" udonationTotal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("rAddress"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" eth3 "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" eth1 "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" ether"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("eth1 "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("999999999999999999")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n eth "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("concat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n eth1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('" (wei)"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n eth "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("concat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n eth3"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('" (eth)"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("concat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("recipient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n eth\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'0x\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n contractAddressString"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n message"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'mint timestamp\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'contract\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'value\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'vitalik.eth signer recipient\'')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 產生 SVG,以 base64 來編碼")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice Generate SVG, b64 encode it, construct an ERC721 token URI.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("constructTokenURI")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prettier-ignore")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" cID "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// generateSVG 會將 cID 傳入,用來產生該 id 對應的 SVG")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" pageSVG "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encode")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generateSVG")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 建構出完整的 URI JSON")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"data:application/json;base64,"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encode")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'{"signed_to":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("cID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("recipient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'", "external_url":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://proofofstake.gitcoin.co/"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'", "timestamp":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("cID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'", "pledge":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n udonationTotal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("cID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("rAddress"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'", "message":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("cID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("writtenMsg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'", "image": "\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"data:image/svg+xml;base64,"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n pageSVG"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\"}'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 利用 token ID 建構出 NFT 的 URI 來建構完整的 URI json ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice Receives json from constructTokenURI\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prettier-ignore")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("tokenURI")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v("\n override\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_exists")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("DoesNotExist")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("constructTokenURI")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 建構出本合約的 URI")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 請特別注意,常見的 NFT 在這邊都會給一個連結指向儲存一個 URI schema 的位置,如 ipfs / http")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 但本合約有趣的地方在於 NFT 本身是以 SVG 的方式文字儲存在區塊鏈上,因此他直接把 URI schema 存在裡面")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("contractURI")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("external")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pure")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"data:application/json;base64,"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encode")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 將以下資料編碼成 base64 格式 */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'"name":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Proof of Stake"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\",'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'"description":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"Vitalik is committed to supporting open-source public goods, he's releasing a book on September 13. We're pre-gaming by raising funds for public goods with a truly unique NFT, where Vitalik signs a message directly on your token. This token is then inserted into your digital copy upon the books release!\"")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\",'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'"image_data":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Yeah, looks like CORS may not be letting this resolve, fix l8r")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\",'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'"external_link":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://proofofstake.gitcoin.co/"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\",'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'"seller_fee_basis_points":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\",'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'"fee_recipient":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0x00"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\"}'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*///////////////////////////////////////////////////////////////\n SIG LOGIC\n //////////////////////////////////////////////////////////////*/")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice https://eips.ethereum.org/EIPS/eip-712\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("DOMAIN_SEPARATOR")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n block"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("chainid "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" INITIAL_CHAIN_ID\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" INITIAL_DOMAIN_SEPARATOR\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("computeDomainSeparator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("computeDomainSeparator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encode")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ProofOfStake_Pages"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 參數: name")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 參數: version")]),t._v("\n block"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("chainid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 參數: chainId")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 參數: verifyingContract")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[51],{372:function(t,s,n){"use strict";n.r(s);var a=n(17),e=Object(a.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"實例解析-proof-of-stake-書籍的捐款合約-part-7-final"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#實例解析-proof-of-stake-書籍的捐款合約-part-7-final"}},[t._v("#")]),t._v(" 實例解析 - Proof of Stake 書籍的捐款合約 Part 7 (final)")]),t._v(" "),s("h2",{attrs:{id:"合約原始碼"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#合約原始碼"}},[t._v("#")]),t._v(" 合約原始碼")]),t._v(" "),s("p",[s("a",{attrs:{href:"https://etherscan.io/address/0x5bf5bcc5362f88721167c1068b58c60cad075aac#code",target:"_blank",rel:"noopener noreferrer"}},[t._v("合約原始碼請點此"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"proofofstake-pages-sol-引用的函式庫與介面"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#proofofstake-pages-sol-引用的函式庫與介面"}},[t._v("#")]),t._v(" "),s("code",[t._v("ProofOfStake_Pages.sol")]),t._v(" 引用的函式庫與介面")]),t._v(" "),s("p",[t._v("ProofOfStake_Pages 合約中引入的函式庫與介面,可以看到以下的結構("),s("code",[t._v("*")]),t._v(" 為本日說明的範圍)")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[t._v("ProofOfStake_Pages"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Ownable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ReentrancyGuard"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721Receiver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721Metadata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" ERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("前文"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IERC165"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Strings"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Counters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Part "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sol\n")])])]),s("h3",{attrs:{id:"主菜-proofofstake-pages-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#主菜-proofofstake-pages-sol"}},[t._v("#")]),t._v(" 主菜:"),s("code",[t._v("ProofOfStake_Pages.sol")])]),t._v(" "),s("p",[t._v("這個 NFT 在設計時引入的 Soulbound (靈魂綁定的概念),因此在 NFT 被鑄造出來後,便禁止轉移與授權相關的函式,只有捐款者本人才能持有。")]),t._v(" "),s("p",[t._v("細節請看程式碼註解。")]),t._v(" "),s("div",{staticClass:"language-solidity extra-class"},[s("pre",{pre:!0,attrs:{class:"language-solidity"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pragma")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("solidity")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">=")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.8.0")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token version number"}},[t._v("0.9.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//SPDX-License-Identifier: Apache-2.0")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@openzeppelin/contracts/access/Ownable.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@openzeppelin/contracts/security/ReentrancyGuard.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@openzeppelin/contracts/utils/Strings.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@openzeppelin/contracts/utils/Counters.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("Base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"base64-sol/base64.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"./libs/Transforms.sol"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 宣告錯誤型態")]),t._v("\nerror "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Soulbound")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 靈魂綁定")]),t._v("\nerror "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("PledgingDisabled")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 關閉捐款")]),t._v("\nerror "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("NotMinimumPledge")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 未達最低捐款額度")]),t._v("\nerror "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("SendFailed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 發送失敗")]),t._v("\nerror "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("InvalidSignature")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 不合法的簽名")]),t._v("\nerror "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ZeroSignature")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// address 0 的簽名")]),t._v("\nerror "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("DoesNotExist")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 不存在")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 提供將 addresses 解碼成對應的 ENS 的介面")]),t._v("\nabstract "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("contract")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ENS_Resolver")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getNames")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("calldata")]),t._v(" addresses"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("external")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v("\n virtual\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 本合約繼承了 ERC721Enumerable, Ownable, 與 ReentrancyGuard 三大合約,而他們彼此還有各自的繼承,可以從前幾篇文章找到")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("contract")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ProofOfStake_Pages")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" ERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Ownable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ReentrancyGuard "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n ENS_Resolver res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ENS_Resolver")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x3671aE578E63FdF66ad4F3E12CC0c0d71Ac7510C")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("using")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Counters")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" Counters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Counter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("using")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Strings")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*///////////////////////////////////////////////////////////////\n TOKEN STORAGE\n //////////////////////////////////////////////////////////////*/")]),t._v("\n\n Counters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Counter "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" _tokenIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" pledgeOpen"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// confirm with team")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" price "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.0001337")]),t._v(" ether"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" tokenlimitperuser "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" publisherSplit "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mapping")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" udonationTotal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//prettier-ignore")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" immutable gitcoin "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xde21F729137C5Af1b01d73aF1dC21eFfa2B8a0d6")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//prettier-ignore")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" immutable sevenStories "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x209D3040C2dEdcb7124be89Fc6849423621EdeaC")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" contractAddressString "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toAsciiString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" currentMessage"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 定義 NFT 的資料結構")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Token")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" recipient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" rAddress"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" sigValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" writtenMsg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n Token"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*///////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("event")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Pledge")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("indexed")]),t._v(" pledgee"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("indexed")]),t._v(" pledgeValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*///////////////////////////////////////////////////////////////\n EIP-712 STORAGE\n //////////////////////////////////////////////////////////////*/")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 寫死 vitalik 的位址")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//prettier-ignore")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" immutable vitalik "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" immutable INITIAL_CHAIN_ID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" immutable INITIAL_DOMAIN_SEPARATOR"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" AUTOGRAPH_TYPEHASH "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"signature(address sender,address recipient,string pledge,string timestamp,string msg)"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*///////////////////////////////////////////////////////////////\n STRUCTOR\n //////////////////////////////////////////////////////////////*/")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 建構子,允許在建構新合約的當下,鑄造已經捐款者的 NFT")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" _donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" _amounts"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ERC721")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Proof Of Stake Pages"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PoSp"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transferOwnership")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xb010ca9Be09C382A9f31b79493bb232bCC319f01")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 設定發行此合約的 chain id 用來驗證簽名")]),t._v("\n INITIAL_CHAIN_ID "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" block"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("chainid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n INITIAL_DOMAIN_SEPARATOR "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("computeDomainSeparator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 發行 NFT 給已經捐款者")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" i "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" _donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("_donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("_donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" resolved "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("resolveENS")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n udonationTotal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("_donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" _amounts"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n _tokenIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("increment")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _tokenIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("current")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_mint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Token")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n recipient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" resolved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n rAddress"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n sigValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _amounts"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" block"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n writtenMsg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Thank you for believing."')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Pledge")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_donors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _amounts"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*///////////////////////////////////////////////////////////////\n PLEDGE LOGIC\n //////////////////////////////////////////////////////////////*/")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 捐款(原則上,這個合約的 NFT 是在這邊被鑄造出來的)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('/**\n * @notice Pledges ETH to GTC & "whitelists" pledger\n */')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//prettier-ignore")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pledge")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("payable")]),t._v(" nonReentrant "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 若捐款關閉中,則觸發錯誤")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pledgeOpen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("PledgingDisabled")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 若捐款的錢低於門檻,觸發錯誤")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" price"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("NotMinimumPledge")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" resolved "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("resolveENS")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 計算發行商的分潤")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint")]),t._v(" sShare "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" publisherSplit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 若呼叫者捐款多次,會更新在 NFT 上")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">=")]),t._v(" tokenlimitperuser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 發送部分收入給 gitcoin")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" success3"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" gitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("call"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" sShare"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("success3"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("SendFailed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 發送分潤給發行商 sevenStories")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" success4"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" sevenStories"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("call"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" sShare"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("success4"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("SendFailed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 更新捐款紀錄")]),t._v("\n udonationTotal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 更新捐款次數")]),t._v("\n pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 反之,這是呼叫者的第一次捐款")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 先發送部分收入給 gitcoin")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" success"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" gitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("call"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" sShare"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("success"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("SendFailed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 再發送分潤給發行商 sevenStories")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" success2"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" sevenStories"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("call"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" sShare"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("success2"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("SendFailed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 更新發送者的捐款紀錄")]),t._v("\n udonationTotal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 更新發送者的捐款次數")]),t._v("\n pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" pledgeLimit"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 建立新的 token ID")]),t._v("\n _tokenIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("increment")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取得新的 token ID")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _tokenIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("current")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 利用新 ID 來鑄造 NFT 給捐款者")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_mint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 將新代幣加入代幣列表中")]),t._v("\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Token")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n recipient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" resolved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 捐款者的 ENS */")]),t._v("\n rAddress"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 捐款者的位址 */")]),t._v("\n sigValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 捐款者的捐款數量 */")]),t._v("\n timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" block"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 捐款當下區塊的時間 */")]),t._v("\n writtenMsg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" currentMessage "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 當前 Vitalik 留下的訊息 */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 觸發捐款事件")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("emit")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Pledge")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 設定訊息")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 只有 vitalik 才能觸發")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("setMessage")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("calldata")]),t._v(" _message"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("external")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" vitalik"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_message"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("60")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n currentMessage "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _message"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 解析特定位址對應的 ENS ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("resolveENS")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" _user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" resolved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" forCall "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n forCall"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" callres "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getNames")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("forCall"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("callres"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n resolved "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("concat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0x"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toAsciiString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n resolved "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" callres"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" resolved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 更新使用者的 NFT,當本合約收到來自 Vitalik 的合法簽名訊息")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice Updates the user token if we have a valid msg from Vitalik\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//prettier-ignore")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("updateIfSigned")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("calldata")]),t._v(" _signature"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("calldata")]),t._v(" _sigValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("calldata")]),t._v(" _timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("calldata")]),t._v(" _message\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("external")]),t._v(" nonReentrant "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),t._v(" v"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),t._v(" r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),t._v(" s"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Transforms"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("splitSignature")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_signature"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),t._v(" hashStruct "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encode")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n AUTOGRAPH_TYPEHASH"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Will be wockis address in live v")]),t._v("\n vitalik"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Signature will be invalid if it isn't to caller &&")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// EIP712: "Addresses are encoded as uint160"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint160")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// EIP712: "values bytes and string are encoded as a keccak256 hash"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_sigValue"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_message"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),t._v(" hash "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"\\x19\\x01"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("DOMAIN_SEPARATOR")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" hashStruct"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" signer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ecrecover")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("signer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" vitalik"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("InvalidSignature")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("signer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ZeroSignature")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenid "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("tokenOfOwnerByIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("msg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sender"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokenid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("writtenMsg "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" _message"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 切換捐款開關")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice Toggles Pledging On / Off\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("togglePledging")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" onlyOwner "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n pledgeOpen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" pledgeOpen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" pledgeOpen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*///////////////////////////////////////////////////////////////\n TOKEN LOGIC\n //////////////////////////////////////////////////////////////*/")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 由於本合約發出的 NFT 為靈魂綁定代幣,因此封印轉移相關函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice SOULBOUND: Block transfers.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("override")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ERC721Enumerable"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" to "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"SOULBOUND: Non-Transferable"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n super"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_beforeTokenTransfer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("from")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 由於本合約發出的 NFT 為靈魂綁定代幣,因此封印授權相關函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice SOULBOUND: Block approvals.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("setApprovalForAll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" operator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" _approved"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v("\n virtual\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("override")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Soulbound")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 由於本合約發出的 NFT 為靈魂綁定代幣,因此封印授權相關函式")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice SOULBOUND: Block approvals.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("approve")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" to"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" tokenId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v("\n virtual\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("override")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" IERC721"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Soulbound")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 用來產生 SVG 的函式,只需要留意裡面用到的變數即可")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice Generate SVG using tParams by index\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generateSVG")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" eth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" message"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("writtenMsg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n message "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("concat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n message "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("concat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("writtenMsg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\"'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" eth1 "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" udonationTotal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("rAddress"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" eth3 "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" eth1 "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" ether"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("eth1 "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("999999999999999999")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n eth "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("concat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n eth1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('" (wei)"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n eth "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("concat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n eth3"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('" (eth)"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("concat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("recipient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n eth\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'0x\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n contractAddressString"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n message"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'mint timestamp\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'contract\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'value\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'vitalik.eth signer recipient\'')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 產生 SVG,以 base64 來編碼")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice Generate SVG, b64 encode it, construct an ERC721 token URI.\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("constructTokenURI")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("private")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prettier-ignore")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" cID "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// generateSVG 會將 cID 傳入,用來產生該 id 對應的 SVG")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" pageSVG "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encode")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generateSVG")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 建構出完整的 URI JSON")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"data:application/json;base64,"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encode")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'{"signed_to":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("cID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("recipient"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'", "external_url":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://proofofstake.gitcoin.co/"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'", "timestamp":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("cID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timestamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'", "pledge":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n udonationTotal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("cID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("rAddress"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'", "message":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n tokens"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("cID"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("writtenMsg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'", "image": "\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"data:image/svg+xml;base64,"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n pageSVG"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\"}'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 利用 token ID 建構出 NFT 的 URI 來建構完整的 URI json ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice Receives json from constructTokenURI\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prettier-ignore")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("tokenURI")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v("\n override\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("_exists")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("revert")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("DoesNotExist")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("constructTokenURI")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 建構出本合約的 URI")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 請特別注意,常見的 NFT 在這邊都會給一個連結指向儲存一個 URI schema 的位置,如 ipfs / http")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 但本合約有趣的地方在於 NFT 本身是以 SVG 的方式文字儲存在區塊鏈上,因此他直接把 URI schema 存在裡面")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("contractURI")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("external")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pure")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"data:application/json;base64,"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Base64"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encode")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* 將以下資料編碼成 base64 格式 */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encodePacked")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'"name":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Proof of Stake"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\",'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'"description":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"Vitalik is committed to supporting open-source public goods, he's releasing a book on September 13. We're pre-gaming by raising funds for public goods with a truly unique NFT, where Vitalik signs a message directly on your token. This token is then inserted into your digital copy upon the books release!\"")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\",'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'"image_data":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Yeah, looks like CORS may not be letting this resolve, fix l8r")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\",'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'"external_link":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://proofofstake.gitcoin.co/"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\",'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'"seller_fee_basis_points":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\",'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('\'"fee_recipient":"\'')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0x00"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'\"}'")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*///////////////////////////////////////////////////////////////\n SIG LOGIC\n //////////////////////////////////////////////////////////////*/")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @notice https://eips.ethereum.org/EIPS/eip-712\n */")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("DOMAIN_SEPARATOR")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n block"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("chainid "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" INITIAL_CHAIN_ID\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" INITIAL_DOMAIN_SEPARATOR\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("computeDomainSeparator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("function")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("computeDomainSeparator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("view")]),t._v(" virtual "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("returns")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n abi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encode")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ProofOfStake_Pages"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 參數: name")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("keccak256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 參數: version")]),t._v("\n block"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("chainid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 參數: chainId")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 參數: verifyingContract")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/52.0e25339e.js b/assets/js/52.49f60f8e.js similarity index 98% rename from assets/js/52.0e25339e.js rename to assets/js/52.49f60f8e.js index 020562f..6adf4b7 100644 --- a/assets/js/52.0e25339e.js +++ b/assets/js/52.49f60f8e.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[52],{372:function(v,_,t){"use strict";t.r(_);var a=t(17),o=Object(a.a)({},(function(){var v=this,_=v._self._c;return _("ContentSlotsDistributor",{attrs:{"slot-key":v.$parent.slotKey}},[_("h1",{attrs:{id:"結語"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#結語"}},[v._v("#")]),v._v(" 結語")]),v._v(" "),_("p",[v._v("本次參與鐵人賽是為了了卻一樁心願,我曾在 2020 年的時候參賽,然而因為一場意外,導致硬碟毀損而中斷該次的參賽。\n恰巧在近一兩年區塊鏈的火熱,導致我身邊的朋友想學習區塊鏈技術,而他們又是完全零基礎的新手,因此我就把平常怎麼教他們入門的東西全部整理起來,編成這個系列。")]),v._v(" "),_("h2",{attrs:{id:"本系列的順序"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#本系列的順序"}},[v._v("#")]),v._v(" 本系列的順序")]),v._v(" "),_("ol",[_("li",[v._v("什麼是區塊鏈?")]),v._v(" "),_("li",[v._v("何謂區塊?何謂鏈?")]),v._v(" "),_("li",[v._v("什麼是交易(Transaction)")]),v._v(" "),_("li",[v._v("燃料(Gas)與手續費(Fee)")]),v._v(" "),_("li",[v._v("帳戶(Account)")]),v._v(" "),_("li",[v._v("網路(Network)")]),v._v(" "),_("li",[v._v("共識機制")]),v._v(" "),_("li",[v._v("工作量證明(Proof-of-Work)")]),v._v(" "),_("li",[v._v("權益證明(Proof-of-Stake)")]),v._v(" "),_("li",[v._v("以太坊生態系的不同層級")]),v._v(" "),_("li",[v._v("以太坊改良提案 Ethereum Improvement Proposals (EIP)")]),v._v(" "),_("li",[v._v("以太坊請求意見稿 Ethereum Request for Comments (ERC)")]),v._v(" "),_("li",[v._v("ERC20 代幣標準")]),v._v(" "),_("li",[v._v("ERC20 例子")]),v._v(" "),_("li",[v._v("ERC721 非同值性代幣(NFT)標準")]),v._v(" "),_("li",[v._v("ERC721 的元資料擴充(metadata extension)")]),v._v(" "),_("li",[v._v("ERC721 的列舉擴充(enumeration extension)")]),v._v(" "),_("li",[v._v("ERC721A 的改進")]),v._v(" "),_("li",[v._v("ERC721R - 有鑑賞期的 NFT")]),v._v(" "),_("li",[v._v("ERC1155 多元代幣標準 - ERC20 + ERC721 我全都要")]),v._v(" "),_("li",[v._v("ERC1155 的案例")]),v._v(" "),_("li",[v._v("POAP - Proof Of Attendance Protocol 參與證明")]),v._v(" "),_("li",[v._v("實例解析 - Proof of Stake 書籍的捐款合約 Part 1")]),v._v(" "),_("li",[v._v("實例解析 - Proof of Stake 書籍的捐款合約 Part 2")]),v._v(" "),_("li",[v._v("實例解析 - Proof of Stake 書籍的捐款合約 Part 3")]),v._v(" "),_("li",[v._v("實例解析 - Proof of Stake 書籍的捐款合約 Part 4")]),v._v(" "),_("li",[v._v("實例解析 - Proof of Stake 書籍的捐款合約 Part 5")]),v._v(" "),_("li",[v._v("實例解析 - Proof of Stake 書籍的捐款合約 Part 6")]),v._v(" "),_("li",[v._v("實例解析 - Proof of Stake 書籍的捐款合約 Part 7 (final)")]),v._v(" "),_("li",[v._v("本篇")])]),v._v(" "),_("h2",{attrs:{id:"本系列編排的方式"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#本系列編排的方式"}},[v._v("#")]),v._v(" 本系列編排的方式")]),v._v(" "),_("h3",{attrs:{id:"區塊鏈常見背景知識"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#區塊鏈常見背景知識"}},[v._v("#")]),v._v(" 區塊鏈常見背景知識")]),v._v(" "),_("p",[v._v("可以看到 1~9 的部分實際上就是剛進入區塊鏈世界裡,因為太常聽到了,導致需要理解的基礎知識。裡頭的名詞也是使用錢包或操作 DApp 都可能會遇到的,因此擺在最前面。")]),v._v(" "),_("h3",{attrs:{id:"dapp-開發者相關知識"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#dapp-開發者相關知識"}},[v._v("#")]),v._v(" DApp 開發者相關知識")]),v._v(" "),_("p",[v._v("而 10 的目的是為了轉向後面 11~29 的 DApp 開發者相關的主題。我認為入門區塊鏈的工程師,多數都是以 DApp 開發的角度來切入,因此把重心都放在與 EIP/ERC 有關的主題上。")]),v._v(" "),_("p",[v._v("在選題方面,我也優先選了 ERC20 (2017 ICO 浪潮)、ERC721/ERC1155 (2021/2022 NFT 浪潮) 這些標準為主,並說明了他們相關的變種與案例。")]),v._v(" "),_("p",[v._v("最後舉了 POAP,一個基於 ERC721 NFT 設計的參與證明機制;以及 Proof of Stake ,也是基於 ERC721 NFT 的合約,但加上了靈魂綁定的細節。希望用這兩個例子幫助大家有更實際的想像。")]),v._v(" "),_("h2",{attrs:{id:"寫在最後"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#寫在最後"}},[v._v("#")]),v._v(" 寫在最後")]),v._v(" "),_("p",[v._v("很開心這次能成功完賽,包含不只是 30 天每天寫文,甚至是每天錄影(對,我同時報名了影片教學),居然還挺下來了(=゚ω゚)ノ")]),v._v(" "),_("p",[v._v("這段時間的文章與影片教學都會統整成一本講義,收錄在 solidity.tw 網站上。文章與影片的部分會以 "),_("code",[v._v("CC 4.0 BY-SA")]),v._v(" 的授權釋出,而程式碼的部分則以 "),_("code",[v._v("Apache-2.0")]),v._v(" 釋出。")]),v._v(" "),_("p",[v._v("希望能以個人微薄之力作為區塊鏈教學的一塊墊腳石。")]),v._v(" "),_("p",[v._v("hydai @ 2022/10/15")])])}),[],!1,null,null,null);_.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[52],{373:function(v,_,t){"use strict";t.r(_);var a=t(17),o=Object(a.a)({},(function(){var v=this,_=v._self._c;return _("ContentSlotsDistributor",{attrs:{"slot-key":v.$parent.slotKey}},[_("h1",{attrs:{id:"結語"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#結語"}},[v._v("#")]),v._v(" 結語")]),v._v(" "),_("p",[v._v("本次參與鐵人賽是為了了卻一樁心願,我曾在 2020 年的時候參賽,然而因為一場意外,導致硬碟毀損而中斷該次的參賽。\n恰巧在近一兩年區塊鏈的火熱,導致我身邊的朋友想學習區塊鏈技術,而他們又是完全零基礎的新手,因此我就把平常怎麼教他們入門的東西全部整理起來,編成這個系列。")]),v._v(" "),_("h2",{attrs:{id:"本系列的順序"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#本系列的順序"}},[v._v("#")]),v._v(" 本系列的順序")]),v._v(" "),_("ol",[_("li",[v._v("什麼是區塊鏈?")]),v._v(" "),_("li",[v._v("何謂區塊?何謂鏈?")]),v._v(" "),_("li",[v._v("什麼是交易(Transaction)")]),v._v(" "),_("li",[v._v("燃料(Gas)與手續費(Fee)")]),v._v(" "),_("li",[v._v("帳戶(Account)")]),v._v(" "),_("li",[v._v("網路(Network)")]),v._v(" "),_("li",[v._v("共識機制")]),v._v(" "),_("li",[v._v("工作量證明(Proof-of-Work)")]),v._v(" "),_("li",[v._v("權益證明(Proof-of-Stake)")]),v._v(" "),_("li",[v._v("以太坊生態系的不同層級")]),v._v(" "),_("li",[v._v("以太坊改良提案 Ethereum Improvement Proposals (EIP)")]),v._v(" "),_("li",[v._v("以太坊請求意見稿 Ethereum Request for Comments (ERC)")]),v._v(" "),_("li",[v._v("ERC20 代幣標準")]),v._v(" "),_("li",[v._v("ERC20 例子")]),v._v(" "),_("li",[v._v("ERC721 非同值性代幣(NFT)標準")]),v._v(" "),_("li",[v._v("ERC721 的元資料擴充(metadata extension)")]),v._v(" "),_("li",[v._v("ERC721 的列舉擴充(enumeration extension)")]),v._v(" "),_("li",[v._v("ERC721A 的改進")]),v._v(" "),_("li",[v._v("ERC721R - 有鑑賞期的 NFT")]),v._v(" "),_("li",[v._v("ERC1155 多元代幣標準 - ERC20 + ERC721 我全都要")]),v._v(" "),_("li",[v._v("ERC1155 的案例")]),v._v(" "),_("li",[v._v("POAP - Proof Of Attendance Protocol 參與證明")]),v._v(" "),_("li",[v._v("實例解析 - Proof of Stake 書籍的捐款合約 Part 1")]),v._v(" "),_("li",[v._v("實例解析 - Proof of Stake 書籍的捐款合約 Part 2")]),v._v(" "),_("li",[v._v("實例解析 - Proof of Stake 書籍的捐款合約 Part 3")]),v._v(" "),_("li",[v._v("實例解析 - Proof of Stake 書籍的捐款合約 Part 4")]),v._v(" "),_("li",[v._v("實例解析 - Proof of Stake 書籍的捐款合約 Part 5")]),v._v(" "),_("li",[v._v("實例解析 - Proof of Stake 書籍的捐款合約 Part 6")]),v._v(" "),_("li",[v._v("實例解析 - Proof of Stake 書籍的捐款合約 Part 7 (final)")]),v._v(" "),_("li",[v._v("本篇")])]),v._v(" "),_("h2",{attrs:{id:"本系列編排的方式"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#本系列編排的方式"}},[v._v("#")]),v._v(" 本系列編排的方式")]),v._v(" "),_("h3",{attrs:{id:"區塊鏈常見背景知識"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#區塊鏈常見背景知識"}},[v._v("#")]),v._v(" 區塊鏈常見背景知識")]),v._v(" "),_("p",[v._v("可以看到 1~9 的部分實際上就是剛進入區塊鏈世界裡,因為太常聽到了,導致需要理解的基礎知識。裡頭的名詞也是使用錢包或操作 DApp 都可能會遇到的,因此擺在最前面。")]),v._v(" "),_("h3",{attrs:{id:"dapp-開發者相關知識"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#dapp-開發者相關知識"}},[v._v("#")]),v._v(" DApp 開發者相關知識")]),v._v(" "),_("p",[v._v("而 10 的目的是為了轉向後面 11~29 的 DApp 開發者相關的主題。我認為入門區塊鏈的工程師,多數都是以 DApp 開發的角度來切入,因此把重心都放在與 EIP/ERC 有關的主題上。")]),v._v(" "),_("p",[v._v("在選題方面,我也優先選了 ERC20 (2017 ICO 浪潮)、ERC721/ERC1155 (2021/2022 NFT 浪潮) 這些標準為主,並說明了他們相關的變種與案例。")]),v._v(" "),_("p",[v._v("最後舉了 POAP,一個基於 ERC721 NFT 設計的參與證明機制;以及 Proof of Stake ,也是基於 ERC721 NFT 的合約,但加上了靈魂綁定的細節。希望用這兩個例子幫助大家有更實際的想像。")]),v._v(" "),_("h2",{attrs:{id:"寫在最後"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#寫在最後"}},[v._v("#")]),v._v(" 寫在最後")]),v._v(" "),_("p",[v._v("很開心這次能成功完賽,包含不只是 30 天每天寫文,甚至是每天錄影(對,我同時報名了影片教學),居然還挺下來了(=゚ω゚)ノ")]),v._v(" "),_("p",[v._v("這段時間的文章與影片教學都會統整成一本講義,收錄在 solidity.tw 網站上。文章與影片的部分會以 "),_("code",[v._v("CC 4.0 BY-SA")]),v._v(" 的授權釋出,而程式碼的部分則以 "),_("code",[v._v("Apache-2.0")]),v._v(" 釋出。")]),v._v(" "),_("p",[v._v("希望能以個人微薄之力作為區塊鏈教學的一塊墊腳石。")]),v._v(" "),_("p",[v._v("hydai @ 2022/10/15")])])}),[],!1,null,null,null);_.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/53.1aba8f81.js b/assets/js/53.bfec46ab.js similarity index 89% rename from assets/js/53.1aba8f81.js rename to assets/js/53.bfec46ab.js index 1c9cdbb..84aa96f 100644 --- a/assets/js/53.1aba8f81.js +++ b/assets/js/53.bfec46ab.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[53],{375:function(t,e,s){"use strict";s.r(e);var r=s(17),i=Object(r.a)({},(function(){var t=this._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[t("h1",{attrs:{id:"那些關於-ethereum-的事"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#那些關於-ethereum-的事"}},[this._v("#")]),this._v(" 那些關於 Ethereum 的事")]),this._v(" "),t("p",[this._v("這是我所撰寫的 Ethereum 101,目標是以輔助學習 Solidity 智能合約開發為主的補充知識。")])])}),[],!1,null,null,null);e.default=i.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[53],{374:function(t,e,s){"use strict";s.r(e);var r=s(17),i=Object(r.a)({},(function(){var t=this._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[t("h1",{attrs:{id:"那些關於-ethereum-的事"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#那些關於-ethereum-的事"}},[this._v("#")]),this._v(" 那些關於 Ethereum 的事")]),this._v(" "),t("p",[this._v("這是我所撰寫的 Ethereum 101,目標是以輔助學習 Solidity 智能合約開發為主的補充知識。")])])}),[],!1,null,null,null);e.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/54.565c39aa.js b/assets/js/54.b525daad.js similarity index 99% rename from assets/js/54.565c39aa.js rename to assets/js/54.b525daad.js index bf29ea1..798f50d 100644 --- a/assets/js/54.565c39aa.js +++ b/assets/js/54.b525daad.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[54],{374:function(e,t,r){"use strict";r.r(t);var n=r(17),o=Object(n.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"深入淺出-eofv1-影片講義"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#深入淺出-eofv1-影片講義"}},[e._v("#")]),e._v(" 深入淺出 EOFv1 影片講義")]),e._v(" "),t("p",[e._v("以下為深入淺出 EOFv1 影片講義的目錄,每個章節皆有對應的影片連結。")]),e._v(" "),t("h2",{attrs:{id:"目錄"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#目錄"}},[e._v("#")]),e._v(" 目錄")]),e._v(" "),t("ol",[t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1A-cj0wJWqQOxbayYWUviqyBo1PvDCMOCJfj_fS526GQ/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("前言"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1oTdYZaZNu4_w223Mlz7Kf0TT5yYvO8eTuolzGpK4WR4/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("什麼是以太坊虛擬機"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1rr8zS8DJ9OBT38WeGiT489M_nU8g0vKEdPingNEMUbQ/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("什麼是以太坊虛擬機組合語言"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1fr9X-3au4nXmoTh_HjaLjptPY8x-MI4QqpzKC5uA87U/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("什麼是以太坊虛擬機操作碼"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1CL9X0mXZ2mXijZJizhRADjTqAWew6Irs_tHEOts2_74/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("什麼是智慧合約"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/15nF0KcwWheuXd5IvrA2OCexsreg3g__cyWPhe33UXGI/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("如何撰寫一份智慧合約,以 Solidity 為例"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/18pCqwjggU424hbcmx9FEYjglX21dXS3qyJwfCQWvqWg/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("如何將智慧合約編譯成以太坊虛擬機位元組碼"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1JeKN6U8FI3H4if7PWMTBttdafUZ6YVes6jDNHvDx3OU/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("如何將智慧合約部署到以太坊主網"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1dBoyT5pytC7qMo8ieejppBL4BEWMEUzF-h0wO19n7rk/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("如何與智慧合約互動"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1Xb_ZQnE5W2--x04uLF9EPQUlEjaKcNL4Hz5vDQ3vOqo/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-7692 EVM Object Format (EOF) v1 Meta"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1GqR9AoiDV1smUW-c0iEstlwOUv7JcjRxQLw2MF_1lho/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EOFv1 Magic & EIP-3541"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1KVnZrf82xTeVpjqKN0km8MRgGGRcKlLHWOpl_envS3k/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-3540 EOFv1"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1SCDIjkFlHEaxp3Z8jE4_J7PwGcvxxXHbGBOkDqEXG9Y/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("現在的合約是怎麼驗證的"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/118HX-YkCT_lhml31ZH-TUzNR7kTJjBAlaQNS5wjhkGs/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-3670: EOF - Code Validation"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1LjLTF9JnZX7gwCaiQR_HHWtYtrqUqNk0gZKEvvmWQ2Q/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("現在的合約是怎麼處理 JUMP 的"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1gscGdLjzmRY0fSKQtQ1O68U-QW9kkXlkJ1aEYc1hynY/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-4200: EOF - Static relative jumps"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/15YM1Ga4vJwbW7Ttmnrj6bizx51TxRlKHrXVL9vf75q0/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("現在的合約是如何存取 Data 的"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/10AiAjhNEMIOTbmk-2VEPHHm8ToEmlDga4fRV4e-8TXQ/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-7480: EOF - Data section access instructions"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1n5L4_GQNEgRySiGPc9u7okz_cuMUH1xYkX4oLyKIVtY/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("現在的合約是如何處理 Stack 的"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1jaYfk-ezC5dU2GeXR6KkSDdncskHSOolnjLIiZ3cRoc/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-663: Introducing SWAPN, DUPN, and EXCHANGE Instructions in the EVM"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1RgWWoCCdQmmN2XMt-VtEbAyZbJQsV19OuN4kK-vDT-w/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("現在的合約是如何處理 CALL 的"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/15tDA8WvHdK7wIic6xMBuketpmRELMgvpJVj9qzJM3KI/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-7069: Revamped CALL instructions"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/180LPQndz_RVsLTW7KLNfk2P4eji8IAfrlA7AfN50tMc/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-4750 Functions"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1FWxSEZeQE_Xwe8ZNVsl0MUzJLA4843RmpZXwkW21Lrc/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-6206 Non-returning functions"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1I2c-pR-I3zecWg__q_nps99-DXSv0Tl1z6oUmyjZe7U/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("現在的合約是怎麼處理部署新合約的"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1VwBG_tzXsOR4D5quIzBEyjsq71PEN1HlKZLaruwas0o/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-7620 EOF Contract Creation"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1bh09-ED2l0Wje3T_0ZfzOiPB7C_FswGn3eu9HKC7Hio/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-7698 EOF Creation transaction"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1qvMvJj47JK-SA6CHDKMjRRernP9Ze7o5l6Z8zD9EbhI/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-5450: EOF - Stack Validation"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1s1t4tdENO05J1xYJUQhIlataFQ92h88zSvLayl_4mJo/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("目前 EOFv1 實作進度"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1bmUhxMKdFybj7wBLWlL7Zfwkpsqvf51y4rwvbyzjugE/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("總結"),t("OutboundLink")],1)])])])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[54],{375:function(e,t,r){"use strict";r.r(t);var n=r(17),o=Object(n.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"深入淺出-eofv1-影片講義"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#深入淺出-eofv1-影片講義"}},[e._v("#")]),e._v(" 深入淺出 EOFv1 影片講義")]),e._v(" "),t("p",[e._v("以下為深入淺出 EOFv1 影片講義的目錄,每個章節皆有對應的影片連結。")]),e._v(" "),t("h2",{attrs:{id:"目錄"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#目錄"}},[e._v("#")]),e._v(" 目錄")]),e._v(" "),t("ol",[t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1A-cj0wJWqQOxbayYWUviqyBo1PvDCMOCJfj_fS526GQ/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("前言"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1oTdYZaZNu4_w223Mlz7Kf0TT5yYvO8eTuolzGpK4WR4/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("什麼是以太坊虛擬機"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1rr8zS8DJ9OBT38WeGiT489M_nU8g0vKEdPingNEMUbQ/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("什麼是以太坊虛擬機組合語言"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1fr9X-3au4nXmoTh_HjaLjptPY8x-MI4QqpzKC5uA87U/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("什麼是以太坊虛擬機操作碼"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1CL9X0mXZ2mXijZJizhRADjTqAWew6Irs_tHEOts2_74/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("什麼是智慧合約"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/15nF0KcwWheuXd5IvrA2OCexsreg3g__cyWPhe33UXGI/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("如何撰寫一份智慧合約,以 Solidity 為例"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/18pCqwjggU424hbcmx9FEYjglX21dXS3qyJwfCQWvqWg/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("如何將智慧合約編譯成以太坊虛擬機位元組碼"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1JeKN6U8FI3H4if7PWMTBttdafUZ6YVes6jDNHvDx3OU/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("如何將智慧合約部署到以太坊主網"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1dBoyT5pytC7qMo8ieejppBL4BEWMEUzF-h0wO19n7rk/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("如何與智慧合約互動"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1Xb_ZQnE5W2--x04uLF9EPQUlEjaKcNL4Hz5vDQ3vOqo/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-7692 EVM Object Format (EOF) v1 Meta"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1GqR9AoiDV1smUW-c0iEstlwOUv7JcjRxQLw2MF_1lho/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EOFv1 Magic & EIP-3541"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1KVnZrf82xTeVpjqKN0km8MRgGGRcKlLHWOpl_envS3k/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-3540 EOFv1"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1SCDIjkFlHEaxp3Z8jE4_J7PwGcvxxXHbGBOkDqEXG9Y/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("現在的合約是怎麼驗證的"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/118HX-YkCT_lhml31ZH-TUzNR7kTJjBAlaQNS5wjhkGs/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-3670: EOF - Code Validation"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1LjLTF9JnZX7gwCaiQR_HHWtYtrqUqNk0gZKEvvmWQ2Q/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("現在的合約是怎麼處理 JUMP 的"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1gscGdLjzmRY0fSKQtQ1O68U-QW9kkXlkJ1aEYc1hynY/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-4200: EOF - Static relative jumps"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/15YM1Ga4vJwbW7Ttmnrj6bizx51TxRlKHrXVL9vf75q0/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("現在的合約是如何存取 Data 的"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/10AiAjhNEMIOTbmk-2VEPHHm8ToEmlDga4fRV4e-8TXQ/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-7480: EOF - Data section access instructions"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1n5L4_GQNEgRySiGPc9u7okz_cuMUH1xYkX4oLyKIVtY/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("現在的合約是如何處理 Stack 的"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1jaYfk-ezC5dU2GeXR6KkSDdncskHSOolnjLIiZ3cRoc/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-663: Introducing SWAPN, DUPN, and EXCHANGE Instructions in the EVM"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1RgWWoCCdQmmN2XMt-VtEbAyZbJQsV19OuN4kK-vDT-w/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("現在的合約是如何處理 CALL 的"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/15tDA8WvHdK7wIic6xMBuketpmRELMgvpJVj9qzJM3KI/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-7069: Revamped CALL instructions"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/180LPQndz_RVsLTW7KLNfk2P4eji8IAfrlA7AfN50tMc/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-4750 Functions"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1FWxSEZeQE_Xwe8ZNVsl0MUzJLA4843RmpZXwkW21Lrc/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-6206 Non-returning functions"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1I2c-pR-I3zecWg__q_nps99-DXSv0Tl1z6oUmyjZe7U/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("現在的合約是怎麼處理部署新合約的"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1VwBG_tzXsOR4D5quIzBEyjsq71PEN1HlKZLaruwas0o/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-7620 EOF Contract Creation"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1bh09-ED2l0Wje3T_0ZfzOiPB7C_FswGn3eu9HKC7Hio/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-7698 EOF Creation transaction"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1qvMvJj47JK-SA6CHDKMjRRernP9Ze7o5l6Z8zD9EbhI/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-5450: EOF - Stack Validation"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1s1t4tdENO05J1xYJUQhIlataFQ92h88zSvLayl_4mJo/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("目前 EOFv1 實作進度"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.google.com/presentation/d/1bmUhxMKdFybj7wBLWlL7Zfwkpsqvf51y4rwvbyzjugE/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("總結"),t("OutboundLink")],1)])])])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/app.436a37a8.js b/assets/js/app.ae23d1a4.js similarity index 82% rename from assets/js/app.436a37a8.js rename to assets/js/app.ae23d1a4.js index 43c10f9..1729a85 100644 --- a/assets/js/app.436a37a8.js +++ b/assets/js/app.ae23d1a4.js @@ -1,4 +1,4 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[]]);!function(t){function e(e){for(var r,a,s=e[0],u=e[1],c=e[2],f=0,p=[];f=e||n<0||m&&t-c>=i}function _(){var t=h();if(b(t))return A(t);s=setTimeout(_,function(t){var n=e-(t-u);return m?p(n,i-(t-c)):n}(t))}function A(t){return s=void 0,E&&r?y(t):(r=o=void 0,a)}function x(){var t=h(),n=b(t);if(r=arguments,o=this,u=t,n){if(void 0===s)return g(u);if(m)return s=setTimeout(_,e),y(u)}return void 0===s&&(s=setTimeout(_,e)),a}return e=v(e)||0,d(n)&&(l=!!n.leading,i=(m="maxWait"in n)?f(v(n.maxWait)||0,e):i,E="trailing"in n?!!n.trailing:E),x.cancel=function(){void 0!==s&&clearTimeout(s),c=0,r=u=o=s=void 0},x.flush=function(){return void 0===s?a:A(h())},x}},function(t,e,n){var r,o; +(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[]]);!function(t){function e(e){for(var r,a,s=e[0],u=e[1],c=e[2],f=0,p=[];f=e||n<0||m&&t-c>=i}function _(){var t=h();if(b(t))return A(t);s=setTimeout(_,function(t){var n=e-(t-u);return m?p(n,i-(t-c)):n}(t))}function A(t){return s=void 0,E&&r?y(t):(r=o=void 0,a)}function x(){var t=h(),n=b(t);if(r=arguments,o=this,u=t,n){if(void 0===s)return g(u);if(m)return s=setTimeout(_,e),y(u)}return void 0===s&&(s=setTimeout(_,e)),a}return e=v(e)||0,d(n)&&(l=!!n.leading,i=(m="maxWait"in n)?f(v(n.maxWait)||0,e):i,E="trailing"in n?!!n.trailing:E),x.cancel=function(){void 0!==s&&clearTimeout(s),c=0,r=u=o=s=void 0},x.flush=function(){return void 0===s?a:A(h())},x}},function(t,e,n){var r,o; /* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress * @license MIT */void 0===(o="function"==typeof(r=function(){var t,e,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
'};function o(t,e,n){return tn?n:t}function i(t){return 100*(-1+t)}n.configure=function(t){var e,n;for(e in t)void 0!==(n=t[e])&&t.hasOwnProperty(e)&&(r[e]=n);return this},n.status=null,n.set=function(t){var e=n.isStarted();t=o(t,r.minimum,1),n.status=1===t?null:t;var u=n.render(!e),c=u.querySelector(r.barSelector),l=r.speed,f=r.easing;return u.offsetWidth,a((function(e){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),s(c,function(t,e,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+i(t)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+i(t)+"%,0)"}:{"margin-left":i(t)+"%"}).transition="all "+e+"ms "+n,o}(t,l,f)),1===t?(s(u,{transition:"none",opacity:1}),u.offsetWidth,setTimeout((function(){s(u,{transition:"all "+l+"ms linear",opacity:0}),setTimeout((function(){n.remove(),e()}),l)}),l)):setTimeout(e,l)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var t=function(){setTimeout((function(){n.status&&(n.trickle(),t())}),r.trickleSpeed)};return r.trickle&&t(),this},n.done=function(t){return t||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(t){var e=n.status;return e?("number"!=typeof t&&(t=(1-e)*o(Math.random()*e,.1,.95)),e=o(e+t,0,.994),n.set(e)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},t=0,e=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===e&&n.start(),t++,e++,r.always((function(){0==--e?(t=0,n.done()):n.set((t-e)/t)})),this):this},n.render=function(t){if(n.isRendered())return document.getElementById("nprogress");c(document.documentElement,"nprogress-busy");var e=document.createElement("div");e.id="nprogress",e.innerHTML=r.template;var o,a=e.querySelector(r.barSelector),u=t?"-100":i(n.status||0),l=document.querySelector(r.parent);return s(a,{transition:"all 0 linear",transform:"translate3d("+u+"%,0,0)"}),r.showSpinner||(o=e.querySelector(r.spinnerSelector))&&p(o),l!=document.body&&c(l,"nprogress-custom-parent"),l.appendChild(e),e},n.remove=function(){l(document.documentElement,"nprogress-busy"),l(document.querySelector(r.parent),"nprogress-custom-parent");var t=document.getElementById("nprogress");t&&p(t)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var t=document.body.style,e="WebkitTransform"in t?"Webkit":"MozTransform"in t?"Moz":"msTransform"in t?"ms":"OTransform"in t?"O":"";return e+"Perspective"in t?"translate3d":e+"Transform"in t?"translate":"margin"};var a=function(){var t=[];function e(){var n=t.shift();n&&n(e)}return function(n){t.push(n),1==t.length&&e()}}(),s=function(){var t=["Webkit","O","Moz","ms"],e={};function n(n){return n=n.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(t,e){return e.toUpperCase()})),e[n]||(e[n]=function(e){var n=document.body.style;if(e in n)return e;for(var r,o=t.length,i=e.charAt(0).toUpperCase()+e.slice(1);o--;)if((r=t[o]+i)in n)return r;return e}(n))}function r(t,e,r){e=n(e),t.style[e]=r}return function(t,e){var n,o,i=arguments;if(2==i.length)for(n in e)void 0!==(o=e[n])&&e.hasOwnProperty(n)&&r(t,n,o);else r(t,i[1],i[2])}}();function u(t,e){return("string"==typeof t?t:f(t)).indexOf(" "+e+" ")>=0}function c(t,e){var n=f(t),r=n+e;u(n,e)||(t.className=r.substring(1))}function l(t,e){var n,r=f(t);u(t,e)&&(n=r.replace(" "+e+" "," "),t.className=n.substring(1,n.length-1))}function f(t){return(" "+(t.className||"")+" ").replace(/\s+/gi," ")}function p(t){t&&t.parentNode&&t.parentNode.removeChild(t)}return n})?r.call(e,n,e,t):r)||(t.exports=o)},function(t,e,n){"use strict";n(147)},function(t,e,n){"use strict";var r=n(155),o=n(11),i=n(1),a=n(46),s=n(157),u=n(33),c=n(30),l=n(158),f=n(88),p=n(52),h=TypeError,d=function(t,e){this.stopped=t,this.result=e},v=d.prototype;t.exports=function(t,e,n){var m,E,y,g,b,_,A,x=n&&n.that,w=!(!n||!n.AS_ENTRIES),B=!(!n||!n.IS_RECORD),C=!(!n||!n.IS_ITERATOR),k=!(!n||!n.INTERRUPTED),P=r(e,x),S=function(t){return m&&p(m,"normal",t),new d(!0,t)},O=function(t){return w?(i(t),k?P(t[0],t[1],S):P(t[0],t[1])):k?P(t,S):P(t)};if(B)m=t.iterator;else if(C)m=t;else{if(!(E=f(t)))throw new h(a(t)+" is not iterable");if(s(E)){for(y=0,g=u(t);g>y;y++)if((b=O(t[y]))&&c(v,b))return b;return new d(!1)}m=l(t,E)}for(_=B?t.next:m.next;!(A=o(_,m)).done;){try{b=O(A.value)}catch(t){p(m,"throw",t)}if("object"==typeof b&&b&&c(v,b))return b}return new d(!1)}},function(t,e,n){"use strict";var r=n(0),o=n(15),i=n(77),a=n(48);t.exports=function(t,e,n,s){s||(s={});var u=s.enumerable,c=void 0!==s.name?s.name:e;if(r(n)&&i(n,c,s),s.global)u?t[e]=n:a(e,n);else{try{s.unsafe?t[e]&&(u=!0):delete t[e]}catch(t){}u?t[e]=n:o.f(t,e,{value:n,enumerable:!1,configurable:!s.nonConfigurable,writable:!s.nonWritable})}return t}},function(t,e,n){"use strict";var r=n(45),o=TypeError;t.exports=function(t){if(r(t))throw new o("Can't call method on "+t);return t}},function(t,e,n){"use strict";t.exports=function(t){return null==t}},function(t,e,n){"use strict";var r=String;t.exports=function(t){try{return r(t)}catch(t){return"Object"}}},function(t,e,n){"use strict";var r=n(19),o=n(2),i=n(48),a=t.exports=o["__core-js_shared__"]||i("__core-js_shared__",{});(a.versions||(a.versions=[])).push({version:"3.39.0",mode:r?"pure":"global",copyright:"© 2014-2024 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.39.0/LICENSE",source:"https://github.com/zloirock/core-js"})},function(t,e,n){"use strict";var r=n(2),o=Object.defineProperty;t.exports=function(t,e){try{o(r,t,{value:e,configurable:!0,writable:!0})}catch(n){r[t]=e}return e}},function(t,e,n){"use strict";var r=n(72),o=n(73),i=r("keys");t.exports=function(t){return i[t]||(i[t]=o(t))}},function(t,e,n){"use strict";t.exports={}},function(t,e,n){"use strict";t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},function(t,e,n){"use strict";var r=n(11),o=n(1),i=n(31);t.exports=function(t,e,n){var a,s;o(t);try{if(!(a=i(t,"return"))){if("throw"===e)throw n;return n}a=r(a,t)}catch(t){s=!0,a=t}if("throw"===e)throw n;if(s)throw a;return o(a),n}},function(t,e,n){var r=n(180),o=n(18),i=Object.prototype,a=i.hasOwnProperty,s=i.propertyIsEnumerable,u=r(function(){return arguments}())?r:function(t){return o(t)&&a.call(t,"callee")&&!s.call(t,"callee")};t.exports=u},function(t,e,n){var r=n(16)(n(12),"Map");t.exports=r},function(t,e){t.exports=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},function(t,e,n){var r=n(200),o=n(207),i=n(209),a=n(210),s=n(211);function u(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e-1&&t%1==0&&t<=9007199254740991}},function(t,e,n){var r=n(10),o=n(60),i=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,a=/^\w*$/;t.exports=function(t,e){if(r(t))return!1;var n=typeof t;return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=t&&!o(t))||(a.test(t)||!i.test(t)||null!=e&&t in Object(e))}},function(t,e,n){var r=n(23),o=n(18);t.exports=function(t){return"symbol"==typeof t||o(t)&&"[object Symbol]"==r(t)}},function(t,e){t.exports=function(t){return t}},function(t,e,n){"use strict";n(271)},function(t,e,n){"use strict";n(154)},function(t,e,n){"use strict";var r=n(5),o=n(11),i=n(124),a=n(27),s=n(28),u=n(66),c=n(8),l=n(74),f=Object.getOwnPropertyDescriptor;e.f=r?f:function(t,e){if(t=s(t),e=u(e),l)try{return f(t,e)}catch(t){}if(c(t,e))return a(!o(i.f,t,e),t[e])}},function(t,e,n){"use strict";var r=n(4),o=n(3),i=n(24),a=Object,s=r("".split);t.exports=o((function(){return!a("z").propertyIsEnumerable(0)}))?function(t){return"String"===i(t)?s(t,""):a(t)}:a},function(t,e,n){"use strict";var r=n(125),o=n(67);t.exports=function(t){var e=r(t,"string");return o(e)?e:e+""}},function(t,e,n){"use strict";var r=n(29),o=n(0),i=n(30),a=n(68),s=Object;t.exports=a?function(t){return"symbol"==typeof t}:function(t){var e=r("Symbol");return o(e)&&i(e.prototype,s(t))}},function(t,e,n){"use strict";var r=n(69);t.exports=r&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},function(t,e,n){"use strict";var r=n(70),o=n(3),i=n(2).String;t.exports=!!Object.getOwnPropertySymbols&&!o((function(){var t=Symbol("symbol detection");return!i(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&r&&r<41}))},function(t,e,n){"use strict";var r,o,i=n(2),a=n(71),s=i.process,u=i.Deno,c=s&&s.versions||u&&u.version,l=c&&c.v8;l&&(o=(r=l.split("."))[0]>0&&r[0]<4?1:+(r[0]+r[1])),!o&&a&&(!(r=a.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=a.match(/Chrome\/(\d+)/))&&(o=+r[1]),t.exports=o},function(t,e,n){"use strict";var r=n(2).navigator,o=r&&r.userAgent;t.exports=o?String(o):""},function(t,e,n){"use strict";var r=n(47);t.exports=function(t,e){return r[t]||(r[t]=e||{})}},function(t,e,n){"use strict";var r=n(4),o=0,i=Math.random(),a=r(1..toString);t.exports=function(t){return"Symbol("+(void 0===t?"":t)+")_"+a(++o+i,36)}},function(t,e,n){"use strict";var r=n(5),o=n(3),i=n(75);t.exports=!r&&!o((function(){return 7!==Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},function(t,e,n){"use strict";var r=n(2),o=n(7),i=r.document,a=o(i)&&o(i.createElement);t.exports=function(t){return a?i.createElement(t):{}}},function(t,e,n){"use strict";var r=n(5),o=n(3);t.exports=r&&o((function(){return 42!==Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype}))},function(t,e,n){"use strict";var r=n(4),o=n(3),i=n(0),a=n(8),s=n(5),u=n(127).CONFIGURABLE,c=n(128),l=n(78),f=l.enforce,p=l.get,h=String,d=Object.defineProperty,v=r("".slice),m=r("".replace),E=r([].join),y=s&&!o((function(){return 8!==d((function(){}),"length",{value:8}).length})),g=String(String).split("String"),b=t.exports=function(t,e,n){"Symbol("===v(h(e),0,7)&&(e="["+m(h(e),/^Symbol\(([^)]*)\).*$/,"$1")+"]"),n&&n.getter&&(e="get "+e),n&&n.setter&&(e="set "+e),(!a(t,"name")||u&&t.name!==e)&&(s?d(t,"name",{value:e,configurable:!0}):t.name=e),y&&n&&a(n,"arity")&&t.length!==n.arity&&d(t,"length",{value:n.arity});try{n&&a(n,"constructor")&&n.constructor?s&&d(t,"prototype",{writable:!1}):t.prototype&&(t.prototype=void 0)}catch(t){}var r=f(t);return a(r,"source")||(r.source=E(g,"string"==typeof e?e:"")),t};Function.prototype.toString=b((function(){return i(this)&&p(this).source||c(this)}),"toString")},function(t,e,n){"use strict";var r,o,i,a=n(129),s=n(2),u=n(7),c=n(20),l=n(8),f=n(47),p=n(49),h=n(50),d=s.TypeError,v=s.WeakMap;if(a||f.state){var m=f.state||(f.state=new v);m.get=m.get,m.has=m.has,m.set=m.set,r=function(t,e){if(m.has(t))throw new d("Object already initialized");return e.facade=t,m.set(t,e),e},o=function(t){return m.get(t)||{}},i=function(t){return m.has(t)}}else{var E=p("state");h[E]=!0,r=function(t,e){if(l(t,E))throw new d("Object already initialized");return e.facade=t,c(t,E,e),e},o=function(t){return l(t,E)?t[E]:{}},i=function(t){return l(t,E)}}t.exports={set:r,get:o,has:i,enforce:function(t){return i(t)?o(t):r(t,{})},getterFor:function(t){return function(e){var n;if(!u(e)||(n=o(e)).type!==t)throw new d("Incompatible receiver, "+t+" required");return n}}}},function(t,e,n){"use strict";var r=n(8),o=n(130),i=n(64),a=n(15);t.exports=function(t,e,n){for(var s=o(e),u=a.f,c=i.f,l=0;lc;)o(r,n=e[c++])&&(~a(l,n)||u(l,n));return l}},function(t,e,n){"use strict";var r=n(134);t.exports=function(t){var e=+t;return e!=e||0===e?0:r(e)}},function(t,e,n){"use strict";var r=n(8),o=n(0),i=n(32),a=n(49),s=n(139),u=a("IE_PROTO"),c=Object,l=c.prototype;t.exports=s?c.getPrototypeOf:function(t){var e=i(t);if(r(e,u))return e[u];var n=e.constructor;return o(n)&&e instanceof n?n.prototype:e instanceof c?l:null}},function(t,e,n){"use strict";var r,o,i,a=n(3),s=n(0),u=n(7),c=n(84),l=n(82),f=n(43),p=n(13),h=n(19),d=p("iterator"),v=!1;[].keys&&("next"in(i=[].keys())?(o=l(l(i)))!==Object.prototype&&(r=o):v=!0),!u(r)||a((function(){var t={};return r[d].call(t)!==t}))?r={}:h&&(r=c(r)),s(r[d])||f(r,d,(function(){return this})),t.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:v}},function(t,e,n){"use strict";var r,o=n(1),i=n(141),a=n(51),s=n(50),u=n(143),c=n(75),l=n(49),f=l("IE_PROTO"),p=function(){},h=function(t){return" + diff --git "a/ethereum-101/02-\344\273\200\351\272\274\346\230\257\345\215\200\345\241\212\344\273\200\351\272\274\346\230\257\351\217\210.html" "b/ethereum-101/02-\344\273\200\351\272\274\346\230\257\345\215\200\345\241\212\344\273\200\351\272\274\346\230\257\351\217\210.html" index b273ba8..ac8caca 100644 --- "a/ethereum-101/02-\344\273\200\351\272\274\346\230\257\345\215\200\345\241\212\344\273\200\351\272\274\346\230\257\351\217\210.html" +++ "b/ethereum-101/02-\344\273\200\351\272\274\346\230\257\345\215\200\345\241\212\344\273\200\351\272\274\346\230\257\351\217\210.html" @@ -8,7 +8,7 @@ - + @@ -36,7 +36,7 @@

我們可以發現這個創始區塊紀錄了多筆由「GENESIS」轉給「以太坊帳戶」的以太轉帳。

# 以第15553296區塊為例

圖片擷取自:https://etherscan.io/txs?block=15553296

在這個區塊中,就能看到很多與智能合約互動的交易,比如說近期熱門的 NFT 就會提供一個 Mint 的函式,讓使用者可以鑄造 NFT 出來。

#

有了對區塊的初步概念,我們就能來探討「鏈」了。

鏈的目的是把區塊有順序地給串起來。而為什麼「順序」如此重要呢?

每個區塊實際上是記錄「交易」,也就是「狀態的變化」,如果順序不同會發生什麼事?

# 以銀行交易為例

Alice 的戶頭有 100 元,Bob 的戶頭有 200 元,海帶的戶頭有 300 元

初始狀態

Alice Bob 海帶
100 200 300

Alice 今天請海帶幫忙代購商品,欠了海帶 200 元。 而 Bob 同時欠了 Alice 100 元。 -Alice 為了能還海帶錢,請 Bob 先還她 100 元。

Bob 還錢後的狀態

Alice Bob 海帶
200 100 300

Alice 這時還給海帶 200 元

最終狀態

Alice Bob 海帶
0 100 500

上面的交易如果順序亂了, Alice 要還錢的交易被放在 Bob 還錢之前,那發生的瞬間就會因為餘額不足導致交易失敗。

# 結語

同理在區塊鏈上前面交易的順序、成功與否都會影響後面的狀態,因此我們需要通過「鏈」的概念確保所有的「區塊」都能以一個不可變動的順序被牢牢的串在一起。

而這,就是區塊鏈。

Last Updated: 2024/12/31 下午3:14:04
Last Updated: 2024/12/31 下午3:17:10
- + diff --git "a/ethereum-101/03-\344\273\200\351\272\274\346\230\257\344\272\244\346\230\223.html" "b/ethereum-101/03-\344\273\200\351\272\274\346\230\257\344\272\244\346\230\223.html" index 9d5c3eb..759d8cf 100644 --- "a/ethereum-101/03-\344\273\200\351\272\274\346\230\257\344\272\244\346\230\223.html" +++ "b/ethereum-101/03-\344\273\200\351\272\274\346\230\257\344\272\244\346\230\223.html" @@ -8,7 +8,7 @@ - + @@ -41,7 +41,7 @@
  • 燃料單位上限(gasLimit)
  • 每單位燃料的優先價格上限(maxPriorityFeePerGas)
  • 每單位燃料的價格上限(maxFeePerGas) -
  • # 結語

    今天就先解釋到這邊,明天再讓我們來聊聊燃料(Gas)的概念。

    - + diff --git "a/ethereum-101/04-\347\207\203\346\226\231\350\210\207\346\211\213\347\272\214\350\262\273.html" "b/ethereum-101/04-\347\207\203\346\226\231\350\210\207\346\211\213\347\272\214\350\262\273.html" index 49ce9e3..34a94c1 100644 --- "a/ethereum-101/04-\347\207\203\346\226\231\350\210\207\346\211\213\347\272\214\350\262\273.html" +++ "b/ethereum-101/04-\347\207\203\346\226\231\350\210\207\346\211\213\347\272\214\350\262\273.html" @@ -8,7 +8,7 @@ - + @@ -34,7 +34,7 @@ GitHub (opens new window)

    # 燃料(Gas)與手續費(Fee)

    在昨天討論交易(Transaction)的時候,想必最後的三個欄位「燃料單位上限(GasLimit)」、「每單位燃料的優先價格上限(MaxPriorityFeePerGas)」、「每單位燃料的價格上限(MaxFeePerGas)」讓大家覺得很困惑吧。

    今天就讓我們來介紹燃料(Gas)與手續費(Fee)的機制。

    # 燃料(Gas)

    在以太坊(Ethereum)上的所有交易實際上都是在「執行特定的操作」,對狀態進行改變(如:帳戶餘額的轉移、部署新合約、與合約互動等)。而進行這些操作自然就會對節點與網路產生「運算資源的消耗」。

    基於使用者付費的原則,發起交易的帳戶便需要為了這些「運算資源」來支付手續費。

    燃料(Gas)便是一種用來表達「被消耗的運算資源」的單位。

    或許你會有個疑問,在電腦或手機上執行軟體,不是都通過消耗的電(瓦特*小時)、或者佔用的運算資源(佔用 CPU 多少執行時間、使用多少記憶體等)來進行計費嗎?為什麼到了以太坊上變成一個奇怪的單位。 這是因為節點並不是執行在「完全相同型號的機器上」,任何人只要滿足運行節點的最低標準需求,便可以在任何的電腦設備(包含但不限於:桌上型電腦、筆記型電腦、開發版、迷你電腦、手機等)上運行。因此幾乎不可能通過硬體規格來進行消耗運算資源的估價。

    為了解決這個問題,以太坊設計了以太坊虛擬機(Ethereum Virtual Machine,簡稱 EVM),將所有運算資源抽象化,對每一種指令的操作都明定價碼,因此便能統一評估「被消耗的運算資源」囉! -關於 EVM 我們會在後續的章節有更深的探討,這邊就暫時不展開了。

    # 燃料數量上限(GasLimit)

    燃料數量上限(GasLimit)是指在一筆交易中,發起者願意支付的最大燃料數量上限。

    請特別留意,執行越多的操作將會需要燃燒更多的燃料 。因此在部署合約或者與合約互動時,通常需要將這個數字設定的高一些,以支付足夠的數量來讓交易能夠完成。

    另外,如果只有轉移 Ether 給其他帳戶,這個操作需要 21,000 單位的燃料作為燃料數量上限。

    # 以轉帳為例

    假設 Alice 要轉給 Bob 一顆 Ether,Alice 將這筆交易的 gas limit 設定為 40,000。而一筆轉移 Ether 的操作需要燃燒 21,000 單位。在執行完轉帳以後,Alice 將會收到一筆 (40,000 - 21,000) = 19,000 單位的燃料退款。

    反之,Alice 太過於小氣,只把 gas limit 設定成 10,000 單位,將導致燃料不夠用的情況,此時這筆交易將會失敗,並被標記成 revert 的狀態,也不會有任何燃料被退回。

    # 改變計價模式的倫敦升級(London Upgrade)

    以太坊在倫敦升級時改變了燃料相關的計價模式,由於此處可以展開的範圍過大,讓我們下一章節再來討論,以下將以升級後的現在進行說明。

    # 基礎費用(Base Fee)

    每個區塊都有基礎費用,當發送者要發出交易時,設定的基礎費用不得低於該區塊的基礎費用。

    請注意,這個基礎費用是通過一個公式進行計算的,其數值與前一個區塊所消耗掉的燃料數量有關。細節我們等倫敦升級章節再行探討。

    當一筆交易被收入區塊中,這筆基礎費用將會直接燒毀,永遠地消失在這世界上。

    燒到的手續費=基礎費用*使用掉的燃料數量。

    # 優先費用(Priority Fee)

    這是個資本主義的世界,就像去迪士尼樂園一樣,不想和其他人一起排隊,可以購買快速通行券來加速搭乘遊樂設施,通過課金來升級體驗。

    在以太坊的世界也一樣,當每筆交易都支付一樣的單位費用時,人人平等,全部慢慢排隊,但也可以通過付點小費給礦工,讓礦工優先將交易放入區塊中,這個機制就是優先費用。

    跟基礎費用不同的是,優先費用所產生的手續費會全部交給礦工。

    給礦工的小費=優先費用*使用掉的燃料數量。

    # 單位燃料費用上限(Max Fee)

    對於使用者而言,每次發送交易都要設定基礎費用與優先費用是非常繁瑣的,為了提升體驗,因此衍生出單位燃料費用上限的概念。

    單位燃料費用上限=基礎費用+優先費用

    而基礎費用又是由公式與前一個區塊狀況而定,使用者無法自行決定,因此對於使用者而言,只需要設定「單位燃料上限」,發起交易的工具就會自動幫忙計算出「優先費用」了。

    # 手續費(Fee)

    總手續費=單位燃料費(Max Fee)*使用的燃料數量(Used Gas)。

    當使用掉的燃數量將大於燃料數量上限時,交易將會失敗,此時的使用掉的燃料數量就會剛好等於燃料數量上限。

    Last Updated: 2024/12/31 下午3:14:04
    Last Updated: 2024/12/31 下午3:17:10
    - + diff --git "a/ethereum-101/05-\345\270\263\346\210\266.html" "b/ethereum-101/05-\345\270\263\346\210\266.html" index eb3bc33..2e99a44 100644 --- "a/ethereum-101/05-\345\270\263\346\210\266.html" +++ "b/ethereum-101/05-\345\270\263\346\210\266.html" @@ -8,7 +8,7 @@ - + @@ -33,7 +33,7 @@ (opens new window) GitHub (opens new window)

    # 帳戶(Account)

    以太坊的帳戶有兩種不同的模式,以產生帳戶的方式來區分:

    1. 以私鑰(Private Key)產生的 EOA (Externally-owned account)
    2. 以部署合約(Deploy Contract)產生的合約帳戶(Contract account)

    # 帳戶的共通特性

    值得注意的是,不論通過何種方式產生帳戶,都具備有以下的特性:

    • 具備餘額(Balance)的資訊,因此可以持有與收發 Ether。
    • 具備呼叫(Call)的能力,因此可以與智能合約進行互動。

    # EOA (Externally-owned account)

    建立一個 EOA 就像是我們去銀行開戶一樣,會建議一個個人的帳戶資訊。只要你擁有私鑰,就能控制這組帳戶。

    EOA 具備以下資訊:

    1. 餘額(Balance):用以儲存該帳戶的 Ether 數量。
    2. Nonce:用以記錄該帳戶已經發出的交易(Transaction)數量

    EOA 可以:

    1. 收發 Ether。
    2. 可以發起交易(Transaction),請特別注意,由於發起交易時一定需要有發送者的簽名(Signature),因此是沒辦法直接使用智能合約發起交易的,整個交易鏈的發起者必然為一個 EOA。

    # 合約帳戶(Contract account)

    建立合約需要使用 EOA 進行合約的部署。 -建立時需要支付燃料,因為部署合約需要在以太坊上儲存合約的程式碼與寫入合約的儲存空間。

    合約帳戶具備以下資訊:

    1. 餘額(Balance):用以儲存該合約持有的 Ether 數量。
    2. Nonce:為該帳戶建立新合約的數量。
    3. 合約的程式碼雜湊值(codeHash):為一組雜湊值,用以查詢資料庫中該帳戶所代表的 EVM 程式碼。
    4. 合約的儲存空間雜湊值(storageRoot 或者 storageHash):為一個 256 位元長度的雜湊值,代表儲存 Merkle Patricia trie 的根節點雜湊值。

    合約帳戶可以:

    1. 收發 Ether。
    2. 只有被 EOA 驅動時,才能當為交易的中繼者,進行合約部署或發送交易。
    Last Updated: 2024/12/31 下午3:14:04
    Last Updated: 2024/12/31 下午3:17:10
    - + diff --git "a/ethereum-101/06-\347\266\262\350\267\257.html" "b/ethereum-101/06-\347\266\262\350\267\257.html" index 4786428..758a3e4 100644 --- "a/ethereum-101/06-\347\266\262\350\267\257.html" +++ "b/ethereum-101/06-\347\266\262\350\267\257.html" @@ -8,7 +8,7 @@ - + @@ -33,7 +33,7 @@ (opens new window) GitHub (opens new window)

    # 網路(Network)

    網路,不是我們上網的含義,而是由多個「節點(Node)」所組成的網路,也就是以太坊根據不同目的所組成的環境。專門用來讓不同層級的開發者與使用者進行「開發」、「測試」、「生產」的不同階段所使用。

    # 鏈 ID (Chain ID)

    在以太坊上,鏈 ID 等同於網路 ID (Network ID)。因此以下都只討論鏈 ID 。

    由於有不同的網路存在,為了讓使用者更好的區分環境,因此每個網路都有其獨特的 ID。

    網路名稱 鏈 ID 目的
    主網(Mainnet) 1 生產環境
    Goerli 測試網(Goerli Testnet) 5 測試環境
    Sepolia 測試網(Sepolia Testnet) 11155111 測試環境

    # 主網(Mainnet)

    為以太坊的正式網路,切記,所有發生在此網路上的交易才是真實的交易。在測試網路上的交易通常是完全無價值的。包含:Ether 幣價、ERC20 Token 的交易、NFT 的交易等等。

    # 測試網(Testnet)

    測試,是一件很重要的事情。千萬不要在生產(Production)環境裡面直接部署任何東西,而為了讓開發者們有測試的環境,以太坊便提供了多個不同的網路。

    # Goerli 測試網

    Goerli 測試網使用權益證明(Proof-of-stake)的共識機制產生區塊。 -不像某些短期用途的測試網,Goerli 是一個被保證會長期營運的穩定測試網,所以智能合約的開發者可以放心的在上面部署應用,且也由於這個特性,目前在主網上很多應用生態在這個測試網上都有一份以供開發者們串接。

    此外,在 The Merge 測試後 Goerli 測試網已經開放「任何人」質押 ETH 成為驗證者。

    # Goerli 相關連結

    # Sepolia 測試網

    Sepolia 測試網也是使用權益證明(Proof-of-stake)作為共識機制。然而這個測試網當時的目的是為了 The Merge 的升級測試所使用,算是較新的測試網。

    此外,在 The Merge 測試後,Sepolia 並只開放給特定人士參與質押 ETH 成為驗證者。

    # Sepolia 相關連結

    # 那些已經被關掉的測試網

    曾經我也部署合約在上面過,現在,請讓我們懷念他們的逝去。

    • Ropsten
    • Rinkeby
    • Kovan
    Last Updated: 2024/12/31 下午3:14:04
    Last Updated: 2024/12/31 下午3:17:10
    - + diff --git "a/ethereum-101/07-\345\205\261\350\255\230\346\251\237\345\210\266.html" "b/ethereum-101/07-\345\205\261\350\255\230\346\251\237\345\210\266.html" index 75670a5..f980233 100644 --- "a/ethereum-101/07-\345\205\261\350\255\230\346\251\237\345\210\266.html" +++ "b/ethereum-101/07-\345\205\261\350\255\230\346\251\237\345\210\266.html" @@ -8,7 +8,7 @@ - + @@ -33,7 +33,7 @@ (opens new window) GitHub (opens new window)

    # 共識機制

    在區塊鏈系統中,通常是由一個龐大數量的節點所構成的網路系統。 -然而,在一個分散系統中,我們無法得知有多少惡意的攻擊者存在,加上多個節點同時間可能收到來自世界各地無數的交易。若沒有一套機制來確保交易的順序、安全性、穩定性、與容錯能力,那整個系統便失去意義了。

    因此,共識機制就被設計出來解決這個難題。

    # 共識的概念

    選舉就是一種共識機制,比如今年火熱無比的縣市長選舉,要選出市長,自然就需要選民們進行投票,而投完票後,以「票多的贏,票少的輸」的策略,決定出誰最終成為市長。

    而在以太坊中,至少需要有 66% 的節點同意以後才能建立共識。

    # 共識機制

    共識機制就是一套規則,定義了在什麼樣的條件或限制下,讓整個網路都同意某個共識的方法。

    共識機制通常定義了:

    1. 誰能參與成為礦工(Miner)或驗證者(Validator),作為挖出區塊或者驗證區塊的人,將獲得出塊獎勵以激勵大家參與。
    2. 如果有人作惡,應該如何被懲罰。
    3. 讓作惡的成本變得非常高,以避免惡意人士的攻擊。

    以太坊在 The Merge 之前跟比特幣(Bitcoin)一樣,都是工作量證明(Proof-of-Work)的共識機制。

    而在 The Merge 後已經改為權益證明(Proof-of-Stake)的共識機制。

    # 不同的共識機制

    在接下來的幾個章節,我們會依序介紹什麼是工作量證明(Ethereum 1.0 的共識機制)與權益證明(Ethereum 2.0 的共識機制)

    Last Updated: 2024/12/31 下午3:14:04
    Last Updated: 2024/12/31 下午3:17:10
    - + diff --git "a/ethereum-101/08-\345\267\245\344\275\234\351\207\217\350\255\211\346\230\216.html" "b/ethereum-101/08-\345\267\245\344\275\234\351\207\217\350\255\211\346\230\216.html" index 8bd8af2..5a5d2d5 100644 --- "a/ethereum-101/08-\345\267\245\344\275\234\351\207\217\350\255\211\346\230\216.html" +++ "b/ethereum-101/08-\345\267\245\344\275\234\351\207\217\350\255\211\346\230\216.html" @@ -8,7 +8,7 @@ - + @@ -35,7 +35,7 @@ (opens new window)

    # 工作量證明(Proof-of-Work)

    設定一個作業,讓所有參與的人提出自己解作業的證明,這個解作業的過程便是所謂的工作量,最終最先解出來的人就是贏家,可以獲得該區塊的記帳權。

    # 就是挖礦囉?

    PoW 基本上是一個計算雜湊值的小遊戲,每一回合(產生區塊的區間)都會設定一個難度(difficulty),當有人在特定的難度下解出符合規則的答案就獲勝取得獎勵,很像是花了巨大的勞力在挖礦,突然間挖出黃金的概念。因此我們稱參與工作量證明的人為「礦工」,而參與工作量證明這件事為「挖礦」。

    # 為什麼 PoW 挖礦很耗電

    因為計算雜湊這件事本身除了算出來以外,沒有任何其他的意義。 但計算的過程卻是需要花很大的力氣在上面,尤其在越多礦工存在的情況,你需要花費更多的成本添購機器,花費更多的電力來供應給這些機器,想像一下你的電腦以 100% 的使用率完全不關機執行的電費,就知道這件事有多麽耗能。

    # 如何參與到 PoW 挖礦

    很抱歉,你沒辦法參與了╮(╯▽╰)╭ 在 The Merge 以後,以太坊不再採用 PoW 作為他的共識機制,因此不再有機會參與 PoW 挖礦了。

    但有個好消息是,你可以改參與權益證明(Proof-of-Stake)的挖礦,只需要你去質押 ETH 與執行節點就能參與喔!

    # 結語

    拋棄 PoW 是個好趨勢,因為不再需要倚賴算力,因此更省電了,北極熊表示感謝。 -而對於想做 AI 應用與遊戲玩家而言更是一件好事,看看精美的顯示卡跳水價格,我們終於能在正常的價格買到該有的品質了。

    真是可喜可賀、可喜可賀!

    Last Updated: 2024/12/31 下午3:14:04
    Last Updated: 2024/12/31 下午3:17:10
    - + diff --git "a/ethereum-101/09-\346\254\212\347\233\212\350\255\211\346\230\216.html" "b/ethereum-101/09-\346\254\212\347\233\212\350\255\211\346\230\216.html" index 3b40c47..c3138cd 100644 --- "a/ethereum-101/09-\346\254\212\347\233\212\350\255\211\346\230\216.html" +++ "b/ethereum-101/09-\346\254\212\347\233\212\350\255\211\346\230\216.html" @@ -8,7 +8,7 @@ - + @@ -32,7 +32,7 @@ 淺入淺出 EVM Object Format (opens new window) GitHub - (opens new window)

    # 權益證明(Proof-of-Stake)

    # 什麼是權益證明

    不同於工作量證明需要礦工花費大量的電力(與礦機成本)來進行計算雜湊值的遊戲。權益證明只需要一台簡單的電腦,執行節點,並把 ETH 質押進以太坊上的一個智能合約中,就可以成為驗證者。

    現在不再需要礦工,而是由驗證者負責去檢查區塊的正確性,若驗證者為人正直,檢查都沒問題就會得到獎勵;反之,作惡的驗證者將會被沒入之前質押的 ETH 作為懲罰。

    # 如何成為驗證者

    想加入驗證者的行列,你不用骨骼驚奇,也不用身體異於常人。你只需要準備 32 顆 ETH(可以直接跟人買),並把這些 ETH 存入合約中,且在你的電腦上執行以下三個軟體:

    1. 執行客戶端(Execution Client)
    2. 共識客戶端(Consensus Client)
    3. 驗證者客戶端(Validator)

    為了避免驗證者可以瞬間大量加入或大量退出,以太坊的 PoS 有限制加入的等待期與退出的冷卻期。一但把 ETH 存入,會先被加入一個隊列中,等待你的節點被正式啟用。

    # 驗證者應該做什麼

    一但啟用成功,驗證者就會從以太坊網路的其他節點接收到新區塊。接著驗證者必須負起責任將區塊中的所有交易依序執行,並檢查區塊的簽名(Signature)是否合法。在這些檢查都完成以後,驗證者需要發出一個投票(在以太坊有個專業術語 attestation)。

    在 PoS 中,每一輪次的驗證都是有嚴格定義的:

    1. 每一個紀元/週期(epoch)包含了 32 個槽(slot
    2. 每個槽為 12 秒

    在每個槽中:

    1. 將有一位驗證者會被隨機選到成為區塊的提議者(block proposer),被選中的驗證者必須負責建立新的區塊,並把這個新區塊發送給其他節點。
    2. 同時會有一群驗證者會被隨機選為「委員會(committee)」,這個委員會必須負責投票與驗證被提議者提出的新區塊。
    Last Updated: 2024/12/31 下午3:14:04
    - + diff --git "a/ethereum-101/10-\344\273\245\345\244\252\345\235\212\347\224\237\346\205\213\347\263\273\347\232\204\344\270\215\345\220\214\345\261\244\347\264\232.html" "b/ethereum-101/10-\344\273\245\345\244\252\345\235\212\347\224\237\346\205\213\347\263\273\347\232\204\344\270\215\345\220\214\345\261\244\347\264\232.html" index 2b37bcb..cf24fb7 100644 --- "a/ethereum-101/10-\344\273\245\345\244\252\345\235\212\347\224\237\346\205\213\347\263\273\347\232\204\344\270\215\345\220\214\345\261\244\347\264\232.html" +++ "b/ethereum-101/10-\344\273\245\345\244\252\345\235\212\347\224\237\346\205\213\347\263\273\347\232\204\344\270\215\345\220\214\345\261\244\347\264\232.html" @@ -8,7 +8,7 @@ - + @@ -32,7 +32,7 @@ 淺入淺出 EVM Object Format (opens new window) GitHub - (opens new window)

    # 以太坊生態系的不同層級

    本篇文章的五層分級概念來自以太坊官網上的 INTRODUCTION TO THE ETHEREUM STACK (opens new window) 文章。

    # 層級

    以太坊是個巨大的生態系,而構築一個生態系必然不只能存在一個特定的層級,而需要多個不同層級的開發者與使用者的參與,才能讓整個生態欣欣向榮。本篇文章就是要介紹這些不同層級的角色,與他們之間在意的點。

    # Level 0: 共識層 Consensus Layer

    雖然在以太坊的文章中,並沒有提到共識層,但我認為這是一切的核心基礎,有個好個共識層與其對應的激勵機制,才能讓礦工/驗證者留下來支撐這個生態,才能讓整個網路有了安全的基礎。

    在這個層級裡,通常都是最底層的共識演算法的開發者,他們專注在解決共識演算法中的細節,包含但不限於:

    1. 設計良好的激勵機制
    2. 設計嚴格的懲罰機制
    3. 對安全性的評估等等

    由於需要的專業知識較深,因此比較屬於研究者的領域,普通的區塊鏈使用者或者 DApp 的開發者並不會對這方面有太多的著墨。

    # Level 1: 以太坊虛擬機 Ethereum Virtual Machine

    除了共識層之外,以太坊與比特幣最大的差異在於以太坊有著良好的智能合約執行環境。

    以太坊虛擬機是執行一切交易的核心,從轉帳、部署合約、與合約互動等,無處不是它的範疇。它就像是你最忠實的手機默默地幫你執行所需要的 App。

    作為使用者當然是不需要知道以太坊虛擬機是怎麼執行的,甚至不需要知道有以太坊虛擬機的角色存在。然而,與參考文內的說法不同,我認為至少智能合約的開發者需要深入理解以太坊虛擬機的指令,理解越深,越能寫出更省燃料,更精巧的合約。

    # Level 2: 智能合約 Smart Contract

    到這裡就是大家常說的 Web 3.0 的開發者了,開發者們會通過撰寫智能合約的程式語言,將商業邏輯部署在以太坊上。

    即使到了智能合約的層級,使用者依然不需要對此層級有什麼了解,因為很多合約不一定是開放原始碼的,既然看不見,那只能從開發者提供的公開介面去做互動,相對受限。

    而作為 DApp 的開發者,這層級開始就是他們吃飯的根據。他們需要熟悉所有智能合約語言與以太坊的特性,這也是許多應用生態系的所在,比如說穩定幣(Stable Coin)、去中心化交易所(Decentralized Exchange)等都是在這個層級被開發出來的。

    # Level 3: 以太坊節點 Ethereum Nodes

    這裡就是使用者們能與以太坊網路上的應用互動的最低層級,通過節點,我們可以存取在區塊鏈上的資料、發送交易到網路上。

    除此之外,也是驗證者參與的層級,他們通過執行節點與驗證者軟體,驗證區塊上每筆交易的正確性,來確保了整個網路的安全與資料的精準度。他們也承載著整個區塊鏈網路的資料(是的,所有的網路狀態都會存在節點中)。

    而節點也提供了最低層級的 JSON-RPC API ,讓應用程式可以與節點互動,這些 API 包含但不限於:

    1. 讀取區塊鏈上的資料,如:使用者帳戶的餘額
    2. 發送交易到網路上,如:轉帳、部署合約、與合約互動

    # Level 4: 以太坊客戶端 APIs Ethereum Client APIs

    直接與以太坊節點互動雖然暴力但簡單有效,但每次都要手動操作底層 JSON-RPC 的 API 實在不甚方便。

    為了方便開發者與使用者與節點互動,在節點之上包裝了一層客戶端,將各種方便的函式庫封裝好,以達到更簡潔與便利的操作。

    以網頁軟體為例,使用 JavaScript API ,如 ether.js 的函式庫來與客戶端互動。若是在伺服器端上的軟體,也能使用 Python 或 Java API 來互動。

    這些 API 建構了很多好用的輪子,讓開發者與使用者能從走路變成騎車,節省很多重複的操作,比如 ETH、Gwei、Wei 間的單位轉換等這類常用但 JSON-RPC API 不提供的功能;又比如把合約的介面做了簡單的封裝,能更直覺地操作合約內的函式與資料。

    # Level 5: 終端使用者的應用層 End-User Applications

    在這裡便是大眾使用者參與的層級,他們不需要知道以太坊虛擬機、不用理解智能合約、不需要關注以太坊節點、也不用操作以太坊客戶端 API、甚至不需要知道這個網站或者軟體的背後是不是使用區塊鏈技術。

    當這件事發生的時候,我認為才是區塊鏈真的走進大眾的眼裡,如同在銀行匯款轉帳時,我們不曾去思考過銀行怎麼儲存貨幣;在買賣股票時,不需要知道內部的撮合演算法與股票紀錄的方式。一切就是對介面的操作,就這麼簡單。

    在這層級解決了特定的痛點與問題,但不需要讓使用者知道這背後是區塊鏈。而這,也是我對區塊鏈應用的未來想像,也是現在從業人員的終極目標。

    Last Updated: 2024/12/31 下午3:14:04
    - + diff --git "a/ethereum-101/11-\344\273\245\345\244\252\345\235\212\346\224\271\350\211\257\346\217\220\346\241\210.html" "b/ethereum-101/11-\344\273\245\345\244\252\345\235\212\346\224\271\350\211\257\346\217\220\346\241\210.html" index 376f5da..839b4a7 100644 --- "a/ethereum-101/11-\344\273\245\345\244\252\345\235\212\346\224\271\350\211\257\346\217\220\346\241\210.html" +++ "b/ethereum-101/11-\344\273\245\345\244\252\345\235\212\346\224\271\350\211\257\346\217\220\346\241\210.html" @@ -8,7 +8,7 @@ - + @@ -46,7 +46,7 @@ 1.4. ERC:應用層級的標準與公約,包含合約的標準,如:代幣標準 EIP-20 (opens new window)以太坊域名系統 EIP-137 (opens new window),函式庫或套件的格式,與錢包的格式等。

  • Meta EIP (或 Process EIP)

  • 流程型 EIP ,描述了對以太坊的流程,或對現存流程的修正。流程型 EIP 定義了除在 Standards Track EIPs 裡面所提的以太坊協議本體外的其他領域。如:提出一個無關以太坊程式碼庫(Ethereum's codebase)的實作。這類型的 EIP 通常需要得到社群的共識,因此開發者與使用者都必須重視以待。例如:程序、指南、對決定流程的改變、對開發工具或開發環境的修改等。

    1. 資訊型 EIP(Informational EIP)

    資訊型的 EIP 描述了對以太坊的設計主題、提供給以太坊社群通用的指南或資訊,但不包含提出新的特性或功能。 且資訊型 EIP 不需要取得以太坊社群的共識或者推薦,因此使用者與開發者不需要特別在意資訊型 EIP,也不一定要遵守裡頭的建議。

    # EIP 的核心概念

    一個 EIP 應著重在擔一個關鍵提案或者想法,越專注在單點,則越容易讓 EIP 被接受。反之,一個包山包海且過分複雜的 EIP 很難被社群接受。 此外,有共通性的修改才需要發起 EIP,若只針對特定的客戶端的修改,那不需要 EIP,只需要去該客戶端那發問即可;反之,當這個修改需要仰賴多個客戶端、或定義會影響到眾多應用的新標準就需要發起 EIP。

    # EIP 的限制

    每一個 EIP 都需達到最低的標準。它必須有一份清晰且對於提案的改良有著完善描述。且提出的實作必須是穩固且不會過份複雜化協議。

    # 關於核心 EIPs 的特殊要求

    若 Core EIP 需要修改以太坊虛擬機,在文件中應參照到該指令或以以下格式定義指令:

    REVERT (0xfe)
    -
    Last Updated: 2024/12/31 下午3:14:04
    Last Updated: 2024/12/31 下午3:17:10
    - + diff --git "a/ethereum-101/12-\344\273\245\345\244\252\345\235\212\350\253\213\346\261\202\346\204\217\350\246\213\347\250\277.html" "b/ethereum-101/12-\344\273\245\345\244\252\345\235\212\350\253\213\346\261\202\346\204\217\350\246\213\347\250\277.html" index 669c196..9ace6cf 100644 --- "a/ethereum-101/12-\344\273\245\345\244\252\345\235\212\350\253\213\346\261\202\346\204\217\350\246\213\347\250\277.html" +++ "b/ethereum-101/12-\344\273\245\345\244\252\345\235\212\350\253\213\346\261\202\346\204\217\350\246\213\347\250\277.html" @@ -8,7 +8,7 @@ - + @@ -33,7 +33,7 @@ (opens new window) GitHub (opens new window)

    # 以太坊請求意見稿 Ethereum Request for Comments (ERC)

    沒錯,目前大家很常聽到的各種代幣標準,如:ERC-20、ERC-721 等,那個前綴的 ERC 的全名就叫做 Ethereum Request for Comments。

    ERC 屬於昨天我們介紹過的 EIP 中,Standards Track EIP 的其中一個子分類。而他定義的便是「應用層級的標準與公約」,因此開發者通常會依循 ERC 的標準來進行相關應用軟體的開發,如多數的代幣都會遵守 ERC-20 的定義。

    # 請求意見稿

    這個名詞其實在學界與業界有個更常見的縮寫 RFC (Request For Comments)。 -通常是用來記錄「規範」、「協議」、「流程」等標準的正式文件,比如說:RFC 793 (opens new window) 定義了傳輸控制協定(TRANSMISSION CONTROL PROTOCOL, TCP)。

    # 常見的 ERC

    • ERC-20 (opens new window) - 定義對「可交換的同質性代幣(Fungible Tokens)」的標準介面,可能的應用場景包含但不限於:投票代幣、質押代幣、虛擬通貨等。

    • ERC-721 (opens new window) - 定義對「非同值性代幣(Non-Fungible Tokens, NFT)」的標準介面,可能的應用場景但不限於:歌曲、藝術、照片等的版權或使用授權。

    • ERC-1155 (opens new window) - 定義「同時涵蓋同值性與非同值性資產(Fungible & Non-Fungible Assets)」的標準介面。

    接下來幾天,我們將依序介紹上面這幾個常見的標準,與他們的變種!

    Last Updated: 2024/12/31 下午3:14:04
    Last Updated: 2024/12/31 下午3:17:10
    - + diff --git "a/ethereum-101/13-ERC20\344\273\243\345\271\243\346\250\231\346\272\226.html" "b/ethereum-101/13-ERC20\344\273\243\345\271\243\346\250\231\346\272\226.html" index 3558367..d167ebd 100644 --- "a/ethereum-101/13-ERC20\344\273\243\345\271\243\346\250\231\346\272\226.html" +++ "b/ethereum-101/13-ERC20\344\273\243\345\271\243\346\250\231\346\272\226.html" @@ -8,7 +8,7 @@ - + @@ -58,7 +58,7 @@

    # 授權(Approval)

    當成功呼叫 approve(address _spender, uint256 _value) 時,必須觸發授權事件。

    _owner:代幣擁有者,address _spender:被授權的花費者,address _value:被授權的可花費額度,uint256

    event Approval(address indexed _owner, address indexed _spender, uint256 _value)
    -
    Last Updated: 2024/12/31 下午3:14:04
    Last Updated: 2024/12/31 下午3:17:10
    - + diff --git "a/ethereum-101/14-ERC20\344\276\213\345\255\220.html" "b/ethereum-101/14-ERC20\344\276\213\345\255\220.html" index 4000624..b4ccd9f 100644 --- "a/ethereum-101/14-ERC20\344\276\213\345\255\220.html" +++ "b/ethereum-101/14-ERC20\344\276\213\345\255\220.html" @@ -8,7 +8,7 @@ - + @@ -32,7 +32,7 @@ 淺入淺出 EVM Object Format (opens new window) GitHub - (opens new window)

    # ERC20 例子

    昨天文鄒鄒地把整個 ERC20 的標準給寫了一遍,然後呢?然後讀者就睡著了╮(╯▽╰)╭

    於是今天讓我們從實際例子下手,來看看 ERC20 到底能做些什麼事情吧!

    # 穩定幣

    通貨,有些約定成俗的規則:

    1. 每個單位貨幣都是等價的,不會因為周杰倫手上的一千塊跟海帶手上的一千塊,都是一千塊。
    2. 標準中設定了「小數位數」,因此可以被分割,比如一角、五毛的概念;跟我們在使用 ETH 時一樣,不是每次都要轉 1 ETH,可以是 0.000001 ETH。

    穩定幣,跟斯斯一樣分很多種,但今天我們只在乎用美元當儲備的穩定幣,也就是他在保證金戶頭裡面存一美金,就發行一美金代幣。

    在這樣的情況下,我們便能在區塊鏈上流通美金的代幣;如同去拉斯維加斯的賭場一樣,賭的是籌碼;在穩定幣的場景裡,我們通過在區塊鏈上流通「美金穩定幣」作為美金的虛擬通貨所使用,可以拿來買書、買 NFT 等。

    # 股票

    沒錯,股票其實也有類似的規則:

    1. 每個 share 都是等價的,張忠謀的一股台積電跟海帶手上的一股台積電都是等價的。不會因為他是張忠謀手上的一股就更值錢。
    2. 而股其實是被切割後的概念了,在以前的台灣股市交易中,我們只能買一張(等於一千股)。

    也因此,有人透過發行 ERC20 在區塊鏈上來當股票使用,每個買代幣的人就自動成為股東,擁有投票跟表決權。

    # 要注意的事情

    ERC20 代幣人人都可以發,名稱可以取一樣,簡稱也可以取一樣,因此必須很嚴格的檢查該代幣的合約位址,才能確保真的是相同的合約,不要輕易被詐騙囉!!!

    Last Updated: 2024/12/31 下午3:14:04
    - + diff --git "a/ethereum-101/15-ERC721\351\235\236\345\220\214\345\200\274\346\200\247\344\273\243\345\271\243\357\274\210NFT\357\274\211\346\250\231\346\272\226.html" "b/ethereum-101/15-ERC721\351\235\236\345\220\214\345\200\274\346\200\247\344\273\243\345\271\243\357\274\210NFT\357\274\211\346\250\231\346\272\226.html" index 4426d99..8dfd994 100644 --- "a/ethereum-101/15-ERC721\351\235\236\345\220\214\345\200\274\346\200\247\344\273\243\345\271\243\357\274\210NFT\357\274\211\346\250\231\346\272\226.html" +++ "b/ethereum-101/15-ERC721\351\235\236\345\220\214\345\200\274\346\200\247\344\273\243\345\271\243\357\274\210NFT\357\274\211\346\250\231\346\272\226.html" @@ -8,7 +8,7 @@ - + @@ -79,7 +79,7 @@ /// 檢查持有者(`_owner`)是否授權全部的 NFT 給第三方帳戶(`_operator`)。 function isApprovedForAll(address _owner, address _operator) external view returns (bool); } -
    Last Updated: 2024/12/31 下午3:14:04
    Last Updated: 2024/12/31 下午3:17:10
    - + diff --git "a/ethereum-101/16-ERC721\347\232\204\345\205\203\350\263\207\346\226\231\346\223\264\345\205\205\357\274\210metadata\357\274\211.html" "b/ethereum-101/16-ERC721\347\232\204\345\205\203\350\263\207\346\226\231\346\223\264\345\205\205\357\274\210metadata\357\274\211.html" index c33bbff..7035165 100644 --- "a/ethereum-101/16-ERC721\347\232\204\345\205\203\350\263\207\346\226\231\346\223\264\345\205\205\357\274\210metadata\357\274\211.html" +++ "b/ethereum-101/16-ERC721\347\232\204\345\205\203\350\263\207\346\226\231\346\223\264\345\205\205\357\274\210metadata\357\274\211.html" @@ -8,7 +8,7 @@ - + @@ -72,7 +72,7 @@ "message":"Thank you for supporting public goods, and enjoy the book!", "image":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MDYuMiIgaGVpZ2h0PSI4MTkuNCIgdmlld0JveD0iMCAwIDYwNi4yIDgxOS40Ij48ZGVmcz48c3R5bGU+LmF7ZmlsbDojZmZmO30uYntmaWxsOm5vbmU7c3Ryb2tlOiNkOWM4ZGI7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLXdpZHRoOjJweDt9LmMsLmQsLmUsLmYsLmcsLmgsLmksLmosLmssLmwsLm0sLm4sLm97aXNvbGF0aW9uOmlzb2xhdGU7fS5jLC5kLC5lLC5mLC5nLC5pLC5qLC5re2ZvbnQtc2l6ZTo1NXB4O30uYywuZXtmaWxsOiNlOTZiNWQ7fS5jLC5kLC5lLC5mLC5nLC5re2ZvbnQtZmFtaWx5Okx1c3REaXNwbGF5LURpZG9uZSwgTHVzdCBEaWRvbmU7fS5kLC5me2ZpbGw6IzliNGE4ZDt9LmV7bGV0dGVyLXNwYWNpbmc6MC4wMmVtO30uZntsZXR0ZXItc3BhY2luZzowLjAyZW07fS5ne2ZpbGw6IzliNGE4Yzt9Lmh7Zm9udC1zaXplOjQ1cHg7ZmlsbDojMGNiNmVhO2ZvbnQtZmFtaWx5Okx1c3QtSXRhbGljLCBMdXN0O2ZvbnQtc3R5bGU6aXRhbGljO30uaSwua3tmaWxsOiM1MGFlNTg7fS5pLC5qe2ZvbnQtZmFtaWx5Okx1c3QtUmVndWxhciwgTHVzdDtsZXR0ZXItc3BhY2luZzowLjA1ZW07fS5qe2ZpbGw6I2VmODkxNjt9LmwsLm17Zm9udC1zaXplOjI5Ljk5cHg7fS5sLC5ue2ZvbnQtZmFtaWx5OkFyaWFsLUJvbGRNVCwgQXJpYWw7Zm9udC13ZWlnaHQ6NzAwO30ubSwub3tmb250LWZhbWlseTpBcmlhbE1ULCBBcmlhbDsgbWFyZ2luLWxlZnQ6IGF1dG87IG1hcmdpbi1yaWdodDogYXV0bzsgd2lkdGg6IDQwJTt9Lm57Zm9udC1zaXplOjIwcHg7fS5ve2ZvbnQtc2l6ZToxOHB4O308L3N0eWxlPjwvZGVmcz48cmVjdCBjbGFzcz0iYSIgd2lkdGg9IjYwNi4yIiBoZWlnaHQ9IjgxOS40Ii8+PHRleHQgY2xhc3M9Im4iPjx0c3BhbiBjbGFzcz0ibiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNTAlIiB5PSI0MiUiPmh5ZGFpLmV0aDwvdHNwYW4+PC90ZXh0Pjx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDc1IDM1Mi44NSkiIGZvbnQtc2l6ZT0iMTgiIGZvbnQtZmFtaWx5PSJBcmlhbE1ULCBBcmlhbCI+PHRzcGFuIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3LjUlIiB5PSIyMDAiPjE2NjI4MzA2OTA8L3RzcGFuPjx0c3BhbiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzNy41JSIgeT0iMjYwIj41MDAwMDAwMDAwMDAwMDAwMCAod2VpKTwvdHNwYW4+PHRzcGFuIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3LjUlIiB5PSIzMjAiPjB4NWJmNWJjYzUzNjJmODg3MjExNjdjMTA2OGI1OGM2MGNhZDA3NWFhYzwvdHNwYW4+PHRzcGFuIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3LjUlIiB5PSIxMjAiPiJUaGFuayB5b3UgZm9yIHN1cHBvcnRpbmcgcHVibGljIGdvb2RzLCBhbmQgZW5qb3kgdGhlIGJvb2shIjwvdHNwYW4+PHRzcGFuIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3LjUlIiB5PSIyMjAiPm1pbnQgdGltZXN0YW1wPC90c3Bhbj48dHNwYW4gdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMzcuNSUiIHk9IjM0MCI+Y29udHJhY3Q8L3RzcGFuPjx0c3BhbiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIzNy41JSIgeT0iMjgwIj52YWx1ZTwvdHNwYW4+PHRzcGFuIHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjM3LjUlIiB5PSIxNDAiPjwvdHNwYW4+PC90ZXh0PjxyZWN0IGNsYXNzPSJiIiB4PSIyMS45IiB5PSIxNjkuNSIgd2lkdGg9IjU2Mi40IiBoZWlnaHQ9IjU2Mi40Ii8+PGcgc3R5bGU9Imlzb2xhdGlvbjppc29sYXRlIj48cGF0aCBkPSJNNDYuNjYsOTguOTN2LS4yOGg0Ljg5VjYwLjcxSDQ2LjY2di0uMjhINjUuOTFjMTIsMCwxOC40MiwzLjE5LDE4LjQyLDExLjE3LDAsOS40LTExLjc3LDExLjI3LTE5Ljg1LDExLjI3aC0xLjZWOTguNjVoNS44M3YuMjhaTTYyLjg4LDgyLjZoMS42YzUuODMsMCw3Ljc1LTMuNDcsNy43NS0xMXMtMS45Mi0xMC44OS03Ljc1LTEwLjg5aC0xLjZaIiBzdHlsZT0iZmlsbDojZTk2YjVkIi8+PC9nPjxnIHN0eWxlPSJpc29sYXRpb246aXNvbGF0ZSI+PHBhdGggZD0iTTEzNSw5MS44NGMwLDUuMTYtMi4yNiw3LjUzLTkuMjEsNy41My02Ljc0LDAtOS40My0yLjI4LTExLjU1LTguNjNDMTEzLDg3LDExMi40NCw3OS41MiwxMDcuNTIsNzkuNTJoLTEuNlY5OC42NWg1LjI4di4yOEg4OS43di0uMjhoNC44OVY2MC43MUg4OS43di0uMjhIMTA5YzUuNjYsMCwxOC40Ny4yMiwxOC40Nyw5LjQ2LDAsNy41NC0xMC43Nyw5LjI3LTE3LjMyLDkuNTR2LjA5YzEwLjc1LDAsMTMuOTQsMy41MiwxNi41OCw5LjE1LDMuMzMsNy4xMiw0LjEzLDguMTcsNS41Myw4LjE3LDIuMiwwLDIuNDctMy4zNSwyLjQ3LTVabS0yOS0xMi42aDEuNmM1LjQ0LDAsNy44MS0yLjg2LDcuODEtOS4zNSwwLTUuMTEtMS44Mi05LjE4LTcuNzktOS4xOGgtMS42MloiIHN0eWxlPSJmaWxsOiM5YjRhOGQiLz48L2c+PGcgc3R5bGU9Imlzb2xhdGlvbjppc29sYXRlIj48cGF0aCBkPSJNMTc4LjY1LDc5LjY4YzAsMTIuNTQtOC44NSwxOS42OS0xOS43MSwxOS42OXMtMTkuNzItNy4xNS0xOS43Mi0xOS42OVMxNDguMDcsNjAsMTU4Ljk0LDYwLDE3OC42NSw2Ny4xNCwxNzguNjUsNzkuNjhabS0xMS44LDBjMC04LjQxLS41Mi0xOS40MS03LjkxLTE5LjQxUzE1MSw3MS4yNywxNTEsNzkuNjhzLjUyLDE5LjQxLDcuOTIsMTkuNDFTMTY2Ljg1LDg4LjEsMTY2Ljg1LDc5LjY4WiIgc3R5bGU9ImZpbGw6I2U5NmI1ZCIvPjwvZz48ZyBzdHlsZT0iaXNvbGF0aW9uOmlzb2xhdGUiPjxwYXRoIGQ9Ik0yMjYuNjgsNzkuNjhjMCwxMi41NC04LjksMTkuNjktMTkuODMsMTkuNjlTMTg3LDkyLjIyLDE4Nyw3OS42OCwxOTUuOTIsNjAsMjA2Ljg1LDYwLDIyNi42OCw2Ny4xNCwyMjYuNjgsNzkuNjhabS0xMS44NywwYzAtOC40MS0uNTItMTkuNDEtOC0xOS40MXMtOCwxMS04LDE5LjQxLjUyLDE5LjQxLDgsMTkuNDFTMjE0LjgxLDg4LjEsMjE0LjgxLDc5LjY4WiIgc3R5bGU9ImZpbGw6IzliNGE4ZCIvPjwvZz48ZyBzdHlsZT0iaXNvbGF0aW9uOmlzb2xhdGUiPjxwYXRoIGQ9Ik0yMzYuNjksOTguOTN2LS4yOGg0Ljg5VjYwLjcxaC00Ljg5di0uMjhoMzMuOTNMMjcyLDczLjY5aC0uMjdsLS4xMS0xYy0uOC03LjU2LTYuODItMTItMTQuMy0xMmgtNC40Vjc5LjEzaC42MWM2LjE4LDAsMTAuMi0yLjU4LDEwLjUtNy43MmwuMDUtMWguMjhsLS45MywxNy43N2gtLjI4bC4wNS0xYy4yOC01LjEyLTMuNDktNy44MS05LjY3LTcuODFoLS42MVY5OC42NWg1Ljgzdi4yOFoiIHN0eWxlPSJmaWxsOiM5YjRhOGMiLz48L2c+PGcgc3R5bGU9Imlzb2xhdGlvbjppc29sYXRlIj48cGF0aCBkPSJNMzA3LjcxLDg3LjM4YzAsNy40Ny02Ljc1LDE0LjE3LTE0Ljc2LDE0LjE3LTYuNDMsMC0xMC44OS00LjI3LTEwLjg5LTEwLjIxLDAtNy43LDYuNjItMTQuMTgsMTQuNzItMTQuMThDMzAzLjI2LDc3LjE2LDMwNy43MSw4MS40NCwzMDcuNzEsODcuMzhabS04LjIzLTQuNjRjMC0yLjY1LS41LTUuMjItMi43NS01LjIyLTUsMC02LjQzLDEzLjg2LTYuNDMsMTguNTQsMCwyLjY2LjQ5LDUuMTMsMi43LDUuMTNDMjk4LDEwMS4xOSwyOTkuNDgsODguMDUsMjk5LjQ4LDgyLjc0WiIgc3R5bGU9ImZpbGw6IzBjYjZlYSIvPjwvZz48ZyBzdHlsZT0iaXNvbGF0aW9uOmlzb2xhdGUiPjxwYXRoIGQ9Ik0zMDAuMTMsMTA1LjQ2YTQuNjEsNC42MSwwLDAsMSw0LjY4LTQuNzcsMy45MywzLjkzLDAsMCwxLDQuMDksNC4xOCwzLjI2LDMuMjYsMCwwLDAtMi43LDMuMjljMCwxLjA4LjQ1LDEuOTMsMS43MSwxLjkzLDIuMTIsMCw0LTIuMzQsNC01Ljc2LDAtMi4wNy0uNjctNC4zMi00LTUuNDlsMy4zNy0yMkgzMDcuNmwwLS4zNmgzLjY1Yy4zMS02LjcsMi41Mi0xMS44OCw5LjE4LTExLjg4LDQuNSwwLDYuNTcsMi40OCw2LjU3LDUuMjdhNC43NSw0Ljc1LDAsMCwxLTQuODIsNWMtMi4yLDAtNC0xLjQ0LTQtNC4yN2EzLjA5LDMuMDksMCwwLDAsMi44OC0zLjJjMC0xLjM1LS41OC0yLjI5LTIuMDctMi4yOS01LjMxLDAtNi44NCwxMS4zOCwxLjQ0LDExLjM4aDMuMmwwLC4zNmgtNC4yN0wzMTYsOTguNzVjLS44Niw1LjQtMy40NywxMi05Ljc3LDEyQzMwMi4yOSwxMTAuNzIsMzAwLjEzLDEwOC4yLDMwMC4xMywxMDUuNDZaIiBzdHlsZT0iZmlsbDojMGNiNmVhIi8+PC9nPjxnIHN0eWxlPSJpc29sYXRpb246aXNvbGF0ZSI+PHBhdGggZD0iTTM0NS44NSw5OC4xbC00LjA3LDEuMTYtLjg4LTE2aC40NGMuODgsNi40NCw0LjQ1LDE1LjYyLDE0LjM1LDE1LjYyLDUsMCw5LTEuNzYsOS01LjgzLDAtOS4yNC0yNC04LjQxLTI0LTIxLjcyQzM0MC42OCw2NCwzNDcuNzcsNjAsMzU2LjU3LDYwYTM5LjM3LDM5LjM3LDAsMCwxLDguNzUsMS4yNmw0LjE4LTEuMTYuNzEsMTMuNTNoLS40NGMtLjg4LTYuMjEtNC4zNC0xMy4xOS0xMy4yLTEzLjE5LTQuNCwwLTcuNDIsMi4wOC03LjQyLDUuNjYsMCw4LjQxLDI0LDcuMDksMjQsMjAuNzksMCw3Ljc1LTguMTMsMTIuNDgtMTcuNDMsMTIuNDhBNDEuNjUsNDEuNjUsMCwwLDEsMzQ1Ljg1LDk4LjFaIiBzdHlsZT0iZmlsbDojNTBhZTU4Ii8+PHBhdGggZD0iTTM4NC42Miw5OC45M3YtLjQ0YzUuNzIsMCw2LjI3LTMsNi4yNy05LjQ2VjYwLjg4Yy04LjkxLDAtMTIuODcsNS4zMy0xMy44LDEzLjYzaC0uNDRsMS40OC0xNC4wN0g0MTVsMS40OCwxNC4wN0g0MTZjLS45My04LjMtNC44OS0xMy42My0xMy44LTEzLjYzVjg5YzAsNi40NC41NSw5LjQ2LDYuMjcsOS40NnYuNDRaIiBzdHlsZT0iZmlsbDojNTBhZTU4Ii8+PC9nPjxnIHN0eWxlPSJpc29sYXRpb246aXNvbGF0ZSI+PHBhdGggZD0iTTQ1NS41NCw4OC40M2MzLjQ2LDcuMiw1LjExLDEwLjA2LDkuMDcsMTAuMDZ2LjQ0SDQ0Mi4xOHYtLjQ0YzUuMjIsMCw0LjE4LTQuMTgsMS40OC05Ljk1bC0xLjM5LTNINDI5LjE4Yy00LDguMzgtMi41OSwxMi45MiwzLjQzLDEyLjkydi40NEg0MTcuMXYtLjQ0YzQsMCw3LjQyLTQuNjcsMTEuNzEtMTMuMzZsMTIuNzEtMjUuNzlaTTQyOS40NSw4NUg0NDJsLTYuMTEtMTMuMDhaIiBzdHlsZT0iZmlsbDojZWY4OTE2Ii8+PHBhdGggZD0iTTUwNC43MSw4Ny42NmM0LjI5LDkuNTEsNS41LDEwLjM5LDguMTQsMTAuMTF2LjQ1YTM2Ljk0LDM2Ljk0LDAsMCwxLTguNzUsMS4yNmMtNi43NiwwLTkuNC0yLjU4LTExLjQzLTguNzQtMS43Ni01LjM0LTMuMjUtMTEuNDQtNi43Ny0xMS40NGE0LjA3LDQuMDcsMCwwLDAtMS44MS40NlY4OWMwLDYuNDQuNDksOS40Niw0LjU2LDkuNDZ2LjQ0SDQ2Ny4yNnYtLjQ0YzUuNSwwLDUuNS0zLDUuNS05LjQ2VjcwLjMzYzAtNi42NSwwLTkuNDYtNS41LTkuNDZ2LS40M2gyMS4zOXYuNDNjLTQuMDcsMC00LjU2LDMtNC41Niw5LjQ2Vjc5LjFsNy03LjY3YzIuMzYtMi41Myw1LjM5LTYuMTYsNS4zOS04LjQxLDAtMS40OS0xLTIuMTUtMy42My0yLjE1di0uNDNoMTYuNjZ2LjQzYy03LDAtMTQuNjgsNy4zMi0xOCwxMC45NWwtNi40OCw3YTE4LDE4LDAsMCwxLDguMjQtMmM1LjU2LDAsOC4xOSwzLjMsMTEuNDQsMTAuODRaIiBzdHlsZT0iZmlsbDojZWY4OTE2Ii8+PC9nPjxnIHN0eWxlPSJpc29sYXRpb246aXNvbGF0ZSI+PHBhdGggZD0iTTU1Mi4yLDczLjY5aC0uMjhsLS4xMS0xYy0uOC03LjU2LTYuODItMTItMTQuMy0xMkg1MzJWNzkuMTNoLjYxYzYuMTgsMCwxMC4yLTIuNTgsMTAuNS03LjcybC4wNi0xaC4yN2wtLjkzLDE3Ljc3aC0uMjhsLjA2LTFjLjI3LTUuMTItMy41LTcuODEtOS42OC03LjgxSDUzMlY5MmMwLDUuMzMuNjEsNi43LDQuNCw2LjcsOS44NywwLDE2LTYuMTUsMTcuMzUtMTVsLjItMS4yNGguMjdsLTIuNjQsMTYuNWgtMzUuOHYtLjI4aDQuODlWNjAuNzFoLTQuODl2LS4yN2gzNVoiIHN0eWxlPSJmaWxsOiM1MGFlNTgiLz48L2c+PHRleHQgY2xhc3M9ImwiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIzNS4xNSAyNjUpIj52aXRhbGlrLmV0aDwvdGV4dD4gPHRleHQgY2xhc3M9Im0iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI2My40OCAyOTUpIj5zaWduZXI8L3RleHQ+IDx0ZXh0IGNsYXNzPSJtIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNDUuNjQgMzczKSI+cmVjaXBpZW50PC90ZXh0Pjwvc3ZnPg==" } -

    # 結語

    通過 URI JSON Schema 我們可以把 NFT 的詳細資訊給記錄在合約中。然而,Proof-of-Stake: Pages 的圖片非常簡單,因此可以使用 SVG 圖片格式直接編碼在 URI 內。

    但,如果 NFT 代表的是一部 4K 影片、一張 8K 圖片等大型檔案,由於儲存成本會變得過高,因此會改用連結到該檔案的方式取代。

    # 結語

    通過 URI JSON Schema 我們可以把 NFT 的詳細資訊給記錄在合約中。然而,Proof-of-Stake: Pages 的圖片非常簡單,因此可以使用 SVG 圖片格式直接編碼在 URI 內。

    但,如果 NFT 代表的是一部 4K 影片、一張 8K 圖片等大型檔案,由於儲存成本會變得過高,因此會改用連結到該檔案的方式取代。

    - + diff --git "a/ethereum-101/17-ERC721\347\232\204\345\210\227\350\210\211\346\223\264\345\205\205.html" "b/ethereum-101/17-ERC721\347\232\204\345\210\227\350\210\211\346\223\264\345\205\205.html" index 574bfd9..9350985 100644 --- "a/ethereum-101/17-ERC721\347\232\204\345\210\227\350\210\211\346\223\264\345\205\205.html" +++ "b/ethereum-101/17-ERC721\347\232\204\345\210\227\350\210\211\346\223\264\345\205\205.html" @@ -8,7 +8,7 @@ - + @@ -56,7 +56,7 @@ // 映射 token ID 到所有 token ID 陣列的 Index // token ID => Index of `_allTokens` mapping(uint256 => uint256) private _allTokensIndex; -

    由於提供此功能所付出的代價不低,因此也有其他的 ERC721 的變種,就讓我們後面再來聊聊吧。

    由於提供此功能所付出的代價不低,因此也有其他的 ERC721 的變種,就讓我們後面再來聊聊吧。

    - + diff --git "a/ethereum-101/18-ERC721A\347\232\204\346\224\271\351\200\262.html" "b/ethereum-101/18-ERC721A\347\232\204\346\224\271\351\200\262.html" index 3090897..c451122 100644 --- "a/ethereum-101/18-ERC721A\347\232\204\346\224\271\351\200\262.html" +++ "b/ethereum-101/18-ERC721A\347\232\204\346\224\271\351\200\262.html" @@ -8,7 +8,7 @@ - + @@ -38,7 +38,7 @@ 我們以上面的表格為例,若 Alice 要將 2 賣給 hydai,這時需要做兩件事情:

    1. 2 的擁有者改成 hydai
    2. 由於 3 的擁有者依然為 Alice,因此需要多寫入一次 Alice 這個擁有者資訊到 3 的格子裡
    Token ID Owner
    0 Alice
    1 X
    2 hydai
    3 Alice
    4 hydai
    5 X

    這時的燃料花費就會比普通的 ERC721 多一次的寫入。

    # 結語

    在實作上,選擇 ERC721、ERC721 Enumeration、ERC721A 等其實都是取捨問題。 只想做最基礎的功能,選 ERC721。 不管儲存的代價,想要在查詢方面容易,選 ERC721 Enumeration。 -想要在鑄造時省錢,但交易時會貴一點,選 ERC721A。

    - + diff --git "a/ethereum-101/19-ERC721R-\346\234\211\351\221\221\350\263\236\346\234\237\347\232\204NFT.html" "b/ethereum-101/19-ERC721R-\346\234\211\351\221\221\350\263\236\346\234\237\347\232\204NFT.html" index c8e12ef..3162279 100644 --- "a/ethereum-101/19-ERC721R-\346\234\211\351\221\221\350\263\236\346\234\237\347\232\204NFT.html" +++ "b/ethereum-101/19-ERC721R-\346\234\211\351\221\221\350\263\236\346\234\237\347\232\204NFT.html" @@ -8,7 +8,7 @@ - + @@ -35,7 +35,7 @@ (opens new window)

    # ERC721R - 有鑑賞期的 NFT

    ERC721R Repo (opens new window)

    如果大家之前有關注到 NFT 相關的新聞,相信一堆專門賣 JPG 圖片的割韭菜專案滿街跑,隨著這些惡劣的團隊毀滅著 NFT 的名聲,越來越多的人不再信任認真做事的團隊,而這便是 ERC721R 想解決的問題。

    # 設計理念

    由於不少的 NFT 專案在發售之際馬上會被有心人士(或者惡劣的團隊本身)捲款潛逃,進而導致 NFT 的價值歸零,讓收藏家血本無歸。而 ERC721R 的標準便新增了鎖倉期間,在鑑賞期內,團隊無法提領合約中的 ETH,必須等鎖倉期過後才能提領。而這段期間只要買家覺得毛毛的,想退款,只需支付交易手續費便能獲得退款。

    # 好處

    對買家而言:

    1. 降低購買風險,最慘也能拿回部分的錢(扣掉手續費)
    2. 不怕專案團隊落跑

    對賣家而言:

    1. 可增加買家意願
    2. 也增加買家的信任,誰叫一堆團隊專門在詐騙呢

    對雙方而言:

    1. 因為可以退款,至少不會公開發售即崩盤

    # 鎖倉期間應該怎麼設計

    如果鎖倉期間過長,好比說發售後 1000 天內都是鑑賞期,代表在這段期間開發者完全不能從裡面提領任何的 ETH,然後呢?然後開發者就餓死了╮(╯▽╰)╭

    在該標準的文件中有提到目前的幾個案例: Exodia 提供 14 天鑑賞期 Curious Addy’s Trading Club 提供 100 天鑑賞期 -CryptoFighters 提供 45 天鑑賞期

    請以團隊不會餓死,又相對合理的時間為主,這樣才能真的對雙方都有好處。

    Last Updated: 2024/12/31 下午3:14:04
    Last Updated: 2024/12/31 下午3:17:10
    - + diff --git "a/ethereum-101/20-ERC1155\345\244\232\345\205\203\344\273\243\345\271\243\346\250\231\346\272\226.html" "b/ethereum-101/20-ERC1155\345\244\232\345\205\203\344\273\243\345\271\243\346\250\231\346\272\226.html" index 9547170..c7055be 100644 --- "a/ethereum-101/20-ERC1155\345\244\232\345\205\203\344\273\243\345\271\243\346\250\231\346\272\226.html" +++ "b/ethereum-101/20-ERC1155\345\244\232\345\205\203\344\273\243\345\271\243\346\250\231\346\272\226.html" @@ -8,7 +8,7 @@ - + @@ -112,7 +112,7 @@ function isApprovedForAll(address _owner, address _operator) external view returns (bool); }

    # 為什麼是我全都要

    實際上,ERC1155 算是對 ERC721 的改良。ERC721 只允許每個代幣只能有一個獨一無二的編號且數量為一。而 ERC1155 在建立代幣時,每個代幣可以指定發行的數量,因此就能做出擁有相同代幣編號,且數量超過一個情境。

    如果想要發行同值性代幣(ERC20),則只需要在 ERC1155 中發行一種編號為 0 的代幣,數量設定該代幣的總發行量即可。 -反之,若想發行非同值性代幣(ERC721),則在 ERC1155 中發行多種相異編號的代幣,每種類的數量都設定為 1 即可。

    - + diff --git "a/ethereum-101/21-ERC1155\347\232\204\346\241\210\344\276\213.html" "b/ethereum-101/21-ERC1155\347\232\204\346\241\210\344\276\213.html" index 8315f9f..829355a 100644 --- "a/ethereum-101/21-ERC1155\347\232\204\346\241\210\344\276\213.html" +++ "b/ethereum-101/21-ERC1155\347\232\204\346\241\210\344\276\213.html" @@ -8,7 +8,7 @@ - + @@ -35,7 +35,7 @@ (opens new window)

    # ERC1155 的案例

    昨天我們講完了 ERC1155 的標準介面,今天來看看有哪些實際的例子是能套用 ERC1155 的吧!

    # Apple 全家桶

    什麼?你說 iPhone 是 ERC1155?iPad 也是?連 macbook 都是?!

    當我們把每個 Apple 的產品都定義為一個 token 時:

    1. iPhone 14 Pro Max 1TB 深紫色
    2. iPhone 14 Pro Max 1TB 金色
    3. iPhone 14 Pro Max 1TB 銀色
    4. iPhone 14 Pro Max 1TB 太空黑色

    如上,可以把不同型號、不同儲存空間大小、不同顏色的組合都設定成一個獨立的 token。 假設本次發佈會只有以四款為主,則就會在當前的 ERC1155 中產生四種不同的 token ID,每一個 token ID 的存量就是 Apple 公司生產的庫存。

    此時每個買到不同手機的人,他的帳戶就會多一一個對應 token ID 的 ERC1155 token,就好比你可以持有多個「ERC20 的代幣一樣」

    而今天 Apple 為了做慈善,拿了一隻「iPhone 14 Pro Max 1TB 深紫色」上面有 Tim Cook 的簽名,並拿去拍賣。這個時候因為上面多了「Tim Cook 的簽名」,因此這個 token 就不是一般的「iPhone 14 Pro Max 1TB 深紫色」。

    這時候我們會在合約中發布一個新的 token ID 象徵著這隻獨一無二的 iPhone,僅此一隻,如果對 NFT 敏感的同學一定會說,啊這是「ERC721」。

    # MMORPG

    在遊戲裡更是如此,當玩家進入遊戲的時候,他所建立的角色可以被做成獨一無二的 token ID 用來表示獨特性,但他打怪獲得的裝備,基本上別人也能打到,這時候就可以用非唯一的數量來發布。

    類型 性質 數量
    角色 唯一,如同身分證 1
    裝備 不唯一,只要夠肝,人人都能打到 N
    課金皮膚或裝備特效 不唯一,只要肯花錢,人人都能買到 N

    如果用 ERC20,便無法表現出「角色」的特性,需要 ERC721 來解決。 -若改用 ERC721,則無法表現出「裝備」與「課金皮膚、裝備、特效」的特性,需要 ERC20 來解決。

    而我全都要的 ERC1155 就能夠取雙方的優點於一身,同時讓 ERC20 & ERC721 共存,這也是多元代幣標準的真正含義。

    Last Updated: 2024/12/31 下午3:14:04
    Last Updated: 2024/12/31 下午3:17:10
    - + diff --git "a/ethereum-101/22-POAP\345\217\203\350\210\207\350\255\211\346\230\216.html" "b/ethereum-101/22-POAP\345\217\203\350\210\207\350\255\211\346\230\216.html" index ea6d51c..15aa9b8 100644 --- "a/ethereum-101/22-POAP\345\217\203\350\210\207\350\255\211\346\230\216.html" +++ "b/ethereum-101/22-POAP\345\217\203\350\210\207\350\255\211\346\230\216.html" @@ -8,7 +8,7 @@ - + @@ -33,7 +33,7 @@ (opens new window) GitHub (opens new window)

    # POAP - Proof Of Attendance Protocol 參與證明

    POAP 被設計出來作為一種數位回憶,在他的格式中記錄了「該活動的名字」、「時間」、「地點」、「紀念圖」等資訊。 -雖然也是使用 ERC721 NFT 的標準為基底,但他加上了些許的限制,比如說 POAP 只發給參加活動的參與者,申請 POAP 的發放者必須承擔起責任檢查領取的人是否真的有參與活動。

    # 使用流程

    活動發放者需要先去 POAP 平台上申請,需要先填寫:

    1. 活動名字與資訊
    2. 活動地點
    3. 發放的時間區間(只有在這個區間內才能領到該活動的 POAP)
    4. 活動的紀念照片(會作為該 POAP 的顯示圖片)

    在申請以後,POAP 組織會審核這個活動,如無問題,通常在 24 小時內就能獲得批准。

    之所以多了一個審核機制是因為目前 POAP 發行在 xDai 區塊鏈上,如我們之前提到的燃料費用問題一樣,POAP 平台是免費提供這個服務,因此燃料費是由他們那邊所支付,為了避免濫用與惡意使用,因此才需要多做審核。

    再通過審核後,就只需要活動的參加者去申請該 POAP 即可獲得。

    # 例子

    # 參與專案開發的證明

    GitPOAP 服務 (opens new window),這個服務連結了你的錢包與 GitHub/GitLab 帳號,當你貢獻過有參與 GitPOAP 服務的專案時,他會發行對應的 POAP 給你,證明你在該年度有貢獻過,以資鼓勵。

    如下圖,是我在 2018~2019 年貢獻過 solidity 與 go-ethereum 兩個專案所獲得的 POAP。

    # 捐款證明

    比如說以下的 POAP 就是在 Mainnet Merge 派對時,只要捐款到特定帳號,就能獲得這枚捐款 POAP。

    本次捐款活動細節,可以參考以下影片: https://www.youtube.com/watch?v=ZY7eXUn7Mpo

    # 相關連結

    官網 (opens new window)

    Last Updated: 2024/12/31 下午3:14:04
    Last Updated: 2024/12/31 下午3:17:10
    - + diff --git "a/ethereum-101/23-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" "b/ethereum-101/23-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" index 26a5aeb..470b629 100644 --- "a/ethereum-101/23-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" +++ "b/ethereum-101/23-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" @@ -8,7 +8,7 @@ - + @@ -233,7 +233,7 @@ return result; } } -
    - + diff --git "a/ethereum-101/24-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" "b/ethereum-101/24-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" index 30c95a1..de43994 100644 --- "a/ethereum-101/24-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" +++ "b/ethereum-101/24-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" @@ -8,7 +8,7 @@ - + @@ -184,7 +184,7 @@ return msg.data; } } -
    - + diff --git "a/ethereum-101/25-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" "b/ethereum-101/25-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" index c3ae247..7145be8 100644 --- "a/ethereum-101/25-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" +++ "b/ethereum-101/25-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" @@ -8,7 +8,7 @@ - + @@ -186,7 +186,7 @@ _status = _NOT_ENTERED; } } -
    - + diff --git "a/ethereum-101/26-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" "b/ethereum-101/26-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" index 2160e1c..823750f 100644 --- "a/ethereum-101/26-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" +++ "b/ethereum-101/26-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" @@ -8,7 +8,7 @@ - + @@ -269,7 +269,7 @@ } } } -
    - + diff --git "a/ethereum-101/27-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" "b/ethereum-101/27-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" index 66bf1f0..b8d53c0 100644 --- "a/ethereum-101/27-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" +++ "b/ethereum-101/27-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" @@ -8,7 +8,7 @@ - + @@ -103,7 +103,7 @@ */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } -
    - + diff --git "a/ethereum-101/28-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" "b/ethereum-101/28-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" index 69f293c..8db66a8 100644 --- "a/ethereum-101/28-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" +++ "b/ethereum-101/28-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" @@ -8,7 +8,7 @@ - + @@ -752,7 +752,7 @@ _allTokens.pop(); } } -
    - + diff --git "a/ethereum-101/29-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" "b/ethereum-101/29-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" index ab3df4a..d33b11e 100644 --- "a/ethereum-101/29-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" +++ "b/ethereum-101/29-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" @@ -8,7 +8,7 @@ - + @@ -591,7 +591,7 @@ ); } } -
    - + diff --git "a/ethereum-101/30-\347\265\220\350\252\236.html" "b/ethereum-101/30-\347\265\220\350\252\236.html" index 1082f40..c8d9401 100644 --- "a/ethereum-101/30-\347\265\220\350\252\236.html" +++ "b/ethereum-101/30-\347\265\220\350\252\236.html" @@ -8,7 +8,7 @@ - + @@ -33,11 +33,11 @@ (opens new window) GitHub (opens new window)

    # 結語

    本次參與鐵人賽是為了了卻一樁心願,我曾在 2020 年的時候參賽,然而因為一場意外,導致硬碟毀損而中斷該次的參賽。 -恰巧在近一兩年區塊鏈的火熱,導致我身邊的朋友想學習區塊鏈技術,而他們又是完全零基礎的新手,因此我就把平常怎麼教他們入門的東西全部整理起來,編成這個系列。

    # 本系列的順序

    1. 什麼是區塊鏈?
    2. 何謂區塊?何謂鏈?
    3. 什麼是交易(Transaction)
    4. 燃料(Gas)與手續費(Fee)
    5. 帳戶(Account)
    6. 網路(Network)
    7. 共識機制
    8. 工作量證明(Proof-of-Work)
    9. 權益證明(Proof-of-Stake)
    10. 以太坊生態系的不同層級
    11. 以太坊改良提案 Ethereum Improvement Proposals (EIP)
    12. 以太坊請求意見稿 Ethereum Request for Comments (ERC)
    13. ERC20 代幣標準
    14. ERC20 例子
    15. ERC721 非同值性代幣(NFT)標準
    16. ERC721 的元資料擴充(metadata extension)
    17. ERC721 的列舉擴充(enumeration extension)
    18. ERC721A 的改進
    19. ERC721R - 有鑑賞期的 NFT
    20. ERC1155 多元代幣標準 - ERC20 + ERC721 我全都要
    21. ERC1155 的案例
    22. POAP - Proof Of Attendance Protocol 參與證明
    23. 實例解析 - Proof of Stake 書籍的捐款合約 Part 1
    24. 實例解析 - Proof of Stake 書籍的捐款合約 Part 2
    25. 實例解析 - Proof of Stake 書籍的捐款合約 Part 3
    26. 實例解析 - Proof of Stake 書籍的捐款合約 Part 4
    27. 實例解析 - Proof of Stake 書籍的捐款合約 Part 5
    28. 實例解析 - Proof of Stake 書籍的捐款合約 Part 6
    29. 實例解析 - Proof of Stake 書籍的捐款合約 Part 7 (final)
    30. 本篇

    # 本系列編排的方式

    # 區塊鏈常見背景知識

    可以看到 1~9 的部分實際上就是剛進入區塊鏈世界裡,因為太常聽到了,導致需要理解的基礎知識。裡頭的名詞也是使用錢包或操作 DApp 都可能會遇到的,因此擺在最前面。

    # DApp 開發者相關知識

    而 10 的目的是為了轉向後面 11~29 的 DApp 開發者相關的主題。我認為入門區塊鏈的工程師,多數都是以 DApp 開發的角度來切入,因此把重心都放在與 EIP/ERC 有關的主題上。

    在選題方面,我也優先選了 ERC20 (2017 ICO 浪潮)、ERC721/ERC1155 (2021/2022 NFT 浪潮) 這些標準為主,並說明了他們相關的變種與案例。

    最後舉了 POAP,一個基於 ERC721 NFT 設計的參與證明機制;以及 Proof of Stake ,也是基於 ERC721 NFT 的合約,但加上了靈魂綁定的細節。希望用這兩個例子幫助大家有更實際的想像。

    # 寫在最後

    很開心這次能成功完賽,包含不只是 30 天每天寫文,甚至是每天錄影(對,我同時報名了影片教學),居然還挺下來了(=゚ω゚)ノ

    這段時間的文章與影片教學都會統整成一本講義,收錄在 solidity.tw 網站上。文章與影片的部分會以 CC 4.0 BY-SA 的授權釋出,而程式碼的部分則以 Apache-2.0 釋出。

    希望能以個人微薄之力作為區塊鏈教學的一塊墊腳石。

    hydai @ 2022/10/15

    Last Updated: 2024/12/31 下午3:14:04
    Last Updated: 2024/12/31 下午3:17:10
    - + diff --git a/ethereum-101/index.html b/ethereum-101/index.html index 9e297c1..5b25b01 100644 --- a/ethereum-101/index.html +++ b/ethereum-101/index.html @@ -8,7 +8,7 @@ - + @@ -32,11 +32,11 @@ 淺入淺出 EVM Object Format (opens new window) GitHub - (opens new window)

    # 那些關於 Ethereum 的事

    這是我所撰寫的 Ethereum 101,目標是以輔助學習 Solidity 智能合約開發為主的補充知識。

    Last Updated: 2024/12/31 下午3:14:04
    - + diff --git a/head-first-eof-lecture-notes/index.html b/head-first-eof-lecture-notes/index.html index de017bf..63ebd57 100644 --- a/head-first-eof-lecture-notes/index.html +++ b/head-first-eof-lecture-notes/index.html @@ -8,7 +8,7 @@ - + @@ -32,7 +32,7 @@ 淺入淺出 EVM Object Format (opens new window) GitHub - (opens new window)

    # 深入淺出 EOFv1 影片講義

    以下為深入淺出 EOFv1 影片講義的目錄,每個章節皆有對應的影片連結。

    # 目錄

    1. 前言 (opens new window)
    2. 什麼是以太坊虛擬機 (opens new window)
    3. 什麼是以太坊虛擬機組合語言 (opens new window)
    4. 什麼是以太坊虛擬機操作碼 (opens new window)
    5. 什麼是智慧合約 (opens new window)
    6. 如何撰寫一份智慧合約,以 Solidity 為例 (opens new window)
    7. 如何將智慧合約編譯成以太坊虛擬機位元組碼 (opens new window)
    8. 如何將智慧合約部署到以太坊主網 (opens new window)
    9. 如何與智慧合約互動 (opens new window)
    10. EIP-7692 EVM Object Format (EOF) v1 Meta (opens new window)
    11. EOFv1 Magic & EIP-3541 (opens new window)
    12. EIP-3540 EOFv1 (opens new window)
    13. 現在的合約是怎麼驗證的 (opens new window)
    14. EIP-3670: EOF - Code Validation (opens new window)
    15. 現在的合約是怎麼處理 JUMP 的 (opens new window)
    16. EIP-4200: EOF - Static relative jumps (opens new window)
    17. 現在的合約是如何存取 Data 的 (opens new window)
    18. EIP-7480: EOF - Data section access instructions (opens new window)
    19. 現在的合約是如何處理 Stack 的 (opens new window)
    20. EIP-663: Introducing SWAPN, DUPN, and EXCHANGE Instructions in the EVM (opens new window)
    21. 現在的合約是如何處理 CALL 的 (opens new window)
    22. EIP-7069: Revamped CALL instructions (opens new window)
    23. EIP-4750 Functions (opens new window)
    24. EIP-6206 Non-returning functions (opens new window)
    25. 現在的合約是怎麼處理部署新合約的 (opens new window)
    26. EIP-7620 EOF Contract Creation (opens new window)
    27. EIP-7698 EOF Creation transaction (opens new window)
    28. EIP-5450: EOF - Stack Validation (opens new window)
    29. 目前 EOFv1 實作進度 (opens new window)
    30. 總結 (opens new window)
    Last Updated: 2024/12/31 下午3:14:04
    - + (opens new window)

    # 深入淺出 EOFv1 影片講義

    以下為深入淺出 EOFv1 影片講義的目錄,每個章節皆有對應的影片連結。

    # 目錄

    1. 前言 (opens new window)
    2. 什麼是以太坊虛擬機 (opens new window)
    3. 什麼是以太坊虛擬機組合語言 (opens new window)
    4. 什麼是以太坊虛擬機操作碼 (opens new window)
    5. 什麼是智慧合約 (opens new window)
    6. 如何撰寫一份智慧合約,以 Solidity 為例 (opens new window)
    7. 如何將智慧合約編譯成以太坊虛擬機位元組碼 (opens new window)
    8. 如何將智慧合約部署到以太坊主網 (opens new window)
    9. 如何與智慧合約互動 (opens new window)
    10. EIP-7692 EVM Object Format (EOF) v1 Meta (opens new window)
    11. EOFv1 Magic & EIP-3541 (opens new window)
    12. EIP-3540 EOFv1 (opens new window)
    13. 現在的合約是怎麼驗證的 (opens new window)
    14. EIP-3670: EOF - Code Validation (opens new window)
    15. 現在的合約是怎麼處理 JUMP 的 (opens new window)
    16. EIP-4200: EOF - Static relative jumps (opens new window)
    17. 現在的合約是如何存取 Data 的 (opens new window)
    18. EIP-7480: EOF - Data section access instructions (opens new window)
    19. 現在的合約是如何處理 Stack 的 (opens new window)
    20. EIP-663: Introducing SWAPN, DUPN, and EXCHANGE Instructions in the EVM (opens new window)
    21. 現在的合約是如何處理 CALL 的 (opens new window)
    22. EIP-7069: Revamped CALL instructions (opens new window)
    23. EIP-4750 Functions (opens new window)
    24. EIP-6206 Non-returning functions (opens new window)
    25. 現在的合約是怎麼處理部署新合約的 (opens new window)
    26. EIP-7620 EOF Contract Creation (opens new window)
    27. EIP-7698 EOF Creation transaction (opens new window)
    28. EIP-5450: EOF - Stack Validation (opens new window)
    29. 目前 EOFv1 實作進度 (opens new window)
    30. 總結 (opens new window)
    Last Updated: 2024/12/31 下午3:17:10
    + diff --git "a/head-first-eof/01-\345\211\215\350\250\200.html" "b/head-first-eof/01-\345\211\215\350\250\200.html" index 13b6e7e..05edbdc 100644 --- "a/head-first-eof/01-\345\211\215\350\250\200.html" +++ "b/head-first-eof/01-\345\211\215\350\250\200.html" @@ -8,7 +8,7 @@ - + @@ -35,11 +35,11 @@ (opens new window)

    # 前言

    或許各位同學已經看過我之前為了參加鐵人賽所錄製的「淺入淺出 EVM Object Format」的影片系列,由於當初錄製的時候時程較趕,因此有些內容與背景知識並沒有講得很清楚,有不少同學跟我反應沒有基礎概念很難聽懂與跟上進度,更覺得 EOF 玄之又玄難以理解。

    因此我打算重新錄製新的「深入淺出 EOF」系列,除了原本介紹 EOFv1 相關的 EIPs 以外,盡可能加入更多的基礎知識,希望能夠讓大家更加了解 EVM Object Format。

    # 關於 EOF

    EVM Object format 的第一個版本其實積累了多年來許多針對以太坊虛擬機(EVM)的改善與增強,由於近年來以太坊的發展重心並不在 EVM 本身,更多的是在共識機制、隱私保護、可擴展性等議題,如:PoS、zk-SNARKs、sharding 等等,因此 EVM Object Format 的相關提案雖然已經發展很長的時間了,但一直都沒能進到硬分叉的階段。

    終於在這次的 Pectra 升級中被加入到以太坊主網中,這對於智慧合約開發的發展來說毫無疑問地是個重要的里程碑,不只會改變現在的智慧合約的底層架構,也對靜態分析等相關工具有很大的影響。巧婦難為無米之炊,以前是 EVM 不夠好限制很多,做事情綁手綁腳的,但現在有了 EOF 的出現將為以太坊的智慧合約開發帶來更多的可能性。

    # 大綱

    這次的系列將會分為以下幾個章節:

    1. 前言
    2. 以太坊虛擬機簡介
      1. 什麼是以太坊虛擬機 (Ethereum Virtual Machine, EVM)
      2. 什麼是以太坊虛擬機組合語言 (Ethereum Virtual Machine Assembly Language, EVM Assembly Language)
      3. 什麼是以太坊虛擬機位元組碼 (Ethereum Virtual Machine Bytecode, EVM Bytecode)
    3. 智慧合約簡介
      1. 什麼是智慧合約 (Smart Contract)
      2. 如何撰寫一份智慧合約,以 Solidity 為例
      3. 如何將智慧合約編譯成以太坊虛擬機位元組碼
      4. 如何將智慧合約部署到以太坊主網 (Mainnet)
      5. 如何與智慧合約互動
    4. 什麼是以太坊物件格式 (EVM Object Format, EOF) -
      1. EIP-7692: EVM Object Format (EOF) v1 Meta
      2. EIP-3541: Reject new contract code starting with the 0xEF byte
      3. EIP-3540: EOFv1
      4. 現在的合約是怎麼驗證的
      5. EIP-3670: EOF - Code Validation - Validate EOF bytecode for correctness at the time of deployment
      6. 現在的合約是怎麼處理 JUMP 的
      7. EIP-4200: EOF - Static relative jumps - RJUMP, RJUMPI and RJUMPV instructions with a signed immediate encoding the jump destination
      8. 現在的合約是如何存取 Data 的
      9. EIP-7480: EOF - Data section access instructions
      10. 現在的合約是如何處理 Stack 的
      11. EIP-663: SWAPN, DUPN and EXCHANGE instructions
      12. 現在的合約是如何處理 CALL 的
      13. EIP-7069: Revamped CALL instructions - Introduce EXTCALL, EXTDELEGATECALL and EXTSTATICCALL with simplified semantics
      14. EIP-4750: EOF - Functions - Individual sections for functions with CALLF and RETF instructions
      15. EIP-6206: EOF - JUMPF and non-returning functions - Introduces instruction for chaining function calls
      16. 現在的合約是怎麼處理部署新合約的
      17. EIP-7620: EOF Contract Creation - Introduce EOFCREATE and RETURNCONTRACT instructions
      18. EIP-7698: EOF - Creation transaction - Deploy EOF contracts using creation transactions
      19. EIP-5450: EOF - Stack Validation - Deploy-time validation of stack usage for EOF functions
    5. 總結
    Last Updated: 2024/12/31 下午3:14:04
    Last Updated: 2024/12/31 下午3:17:10
    - + diff --git a/head-first-eof/index.html b/head-first-eof/index.html index 066cdf8..2c9cbf1 100644 --- a/head-first-eof/index.html +++ b/head-first-eof/index.html @@ -8,7 +8,7 @@ - + @@ -32,11 +32,11 @@ 淺入淺出 EVM Object Format (opens new window) GitHub - (opens new window)

    # 深入淺出 EOFv1

    為一系列以 EVM Object Format 為主題的教學課程,包含影片與文章,為「淺入淺出 EOF」的重製版本。將以完全初學者的角度入手,從各種背景知識開始介紹,由淺入深的讓讀者對 EOF 能有更完整的印象。

    Last Updated: 2024/12/31 下午3:14:04
    - + diff --git a/index.html b/index.html index c721999..e5abc9a 100644 --- a/index.html +++ b/index.html @@ -8,7 +8,7 @@ - + @@ -33,7 +33,7 @@ (opens new window) GitHub (opens new window)

    # 一本關於 Ethereum 與 Solidity 智能合約的書

    # 寫在最前面

    本書並無預定的完成日期,是以滾動式更新為主,目前會有以下幾個系列:

    1. 那些關於 Ethereum 的事:為一系列與 Ethereum 為主的文章。
    2. 在 2022 年,我們該如何寫智能合約 (opens new window):為一系列以智能合約程式語言 Soliidty 0.8.x 為基礎的影片教學課程。
    3. 在智能合約背後,你不知道的事:為一系列相對進階的智能合約開發技巧的文章與教學影片(目前還在規劃中,預計 2023 年六月底前發布)。
    4. 那些觀眾想知道的事:為觀眾透過 GitHub Issue 向海帶我提問的主題或者問題,將會以文章的方式來呈現(目前還在寫作中,等 3 完成以後才會繼續進行)
    5. 淺入淺出 EVM Object Format (opens new window):為一系列以 EVM Object Format 為主題的影片教學課程。包含但不限於 EIP-7692 所包含的 EIPs 與 EOFv1 的優點和改進的好處。
    6. 深入淺出 EVM Object Format:為一系列以 EVM Object Format 為主題的教學課程,包含影片與文章,為「淺入淺出 EOF」的重製版本。將以完全初學者的角度入手,從各種背景知識開始介紹,由淺入深的讓讀者對 EOF 能有更完整的印象。 -

    如果你有想看的主題,或者認為哪些主題應該被涵蓋在本書中,請使用 Issue 來進行發問。

    # 關於這本書的由來

    我曾經於 2018 年末錄製了一份 Solidity 智能合約的教學影片1 (opens new window),當時以 Solidity 版本 0.4.x 的語法進行課程的設計與規劃。然而,一個新語言的演進是非常迅速的。如今的 Solidity 已經是 0.8.x 版本,很多的語法、例子已經不再適用。

    最近幾個月剛好在教身邊的朋友如何寫合約,因此決定把過往的教材拿出來翻修,並搭配現在的 Ethereum The Merge 的時機點,來聊聊關於 Ethereum 1.0, 2.0 與 Solidity 智能合約開發的那些事。

    # 獲獎資訊

    謝謝 2022 年 iThome 鐵人賽評審的認可。

    本作品中的「那些關於 Ethereum 的事 (opens new window)」獲得「Web 3 組佳作」;「在 2022 年,我們該如何寫智能合約 (opens new window)」更是獲得「影片教學組優選」。

    # 一些相關的連結

    Last Updated: 2024/12/31 下午3:14:04
    - +

    如果你有想看的主題,或者認為哪些主題應該被涵蓋在本書中,請使用 Issue 來進行發問。

    # 關於這本書的由來

    我曾經於 2018 年末錄製了一份 Solidity 智能合約的教學影片1 (opens new window),當時以 Solidity 版本 0.4.x 的語法進行課程的設計與規劃。然而,一個新語言的演進是非常迅速的。如今的 Solidity 已經是 0.8.x 版本,很多的語法、例子已經不再適用。

    最近幾個月剛好在教身邊的朋友如何寫合約,因此決定把過往的教材拿出來翻修,並搭配現在的 Ethereum The Merge 的時機點,來聊聊關於 Ethereum 1.0, 2.0 與 Solidity 智能合約開發的那些事。

    # 獲獎資訊

    謝謝 2022 年 iThome 鐵人賽評審的認可。

    本作品中的「那些關於 Ethereum 的事 (opens new window)」獲得「Web 3 組佳作」;「在 2022 年,我們該如何寫智能合約 (opens new window)」更是獲得「影片教學組優選」。

    # 一些相關的連結

    Last Updated: 2024/12/31 下午3:17:10
    +