From 26ac0d5d7ff766fcca134cb26a6f95146414bb78 Mon Sep 17 00:00:00 2001 From: hydai Date: Thu, 5 Dec 2024 13:58:25 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=BE=A9=20head=20first=20eofv1=20?= =?UTF-8?q?=E7=9A=84=E9=80=B2=E5=85=A5=E9=BB=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hydai --- .vuepress/dist/404.html | 4 +- .../js/{23.4ce5df8e.js => 23.fbd9727b.js} | 2 +- .../js/{24.f6fc25b5.js => 24.d8798d04.js} | 2 +- .../js/{25.f69d7f61.js => 25.2cda7a07.js} | 2 +- .../js/{26.1239795f.js => 26.ffa8d039.js} | 2 +- .../js/{27.c7f13266.js => 27.729b555d.js} | 2 +- .../js/{28.7490b05b.js => 28.9d532788.js} | 2 +- .../js/{29.45df8ad8.js => 29.cc51b3c9.js} | 2 +- .../js/{30.6ae513dc.js => 30.6d713582.js} | 2 +- .../js/{31.50722645.js => 31.ede9d797.js} | 2 +- .../js/{32.7d8a5f03.js => 32.2ef16d92.js} | 2 +- .../js/{33.4a908e19.js => 33.cc69c412.js} | 2 +- .../js/{35.e73f9098.js => 35.770ffdf6.js} | 2 +- .../js/{36.dc5f1bb9.js => 36.f857026a.js} | 2 +- .../js/{37.4f5e73b1.js => 37.ed93802d.js} | 2 +- .../js/{38.35ee4ee4.js => 38.7d25c164.js} | 2 +- .../js/{39.1a15401d.js => 39.27a34c86.js} | 2 +- .../js/{41.dca031ce.js => 41.0145fe58.js} | 2 +- .../js/{42.4dcfb5f8.js => 42.55c3ac28.js} | 2 +- .../js/{43.3a95c013.js => 43.dcf8fa43.js} | 2 +- .../js/{44.6d57de51.js => 44.df717947.js} | 2 +- .../js/{45.0956e95c.js => 45.7358417c.js} | 2 +- .../js/{46.7d8be4f3.js => 46.bdb025a8.js} | 2 +- .../js/{47.a93f348e.js => 47.f895a2cf.js} | 2 +- .../js/{48.1f5224ec.js => 48.e34e19d6.js} | 2 +- .../js/{49.5425ea98.js => 49.fe0613a1.js} | 2 +- .../js/{51.c0c6d69d.js => 51.d6749299.js} | 2 +- .../js/{52.2ca06770.js => 52.a91199e7.js} | 2 +- .../js/{53.27e1c49e.js => 53.c312c13b.js} | 2 +- .../js/{54.978645b9.js => 54.1d257938.js} | 2 +- .vuepress/dist/assets/js/55.6f4fc799.js | 1 + .../js/{app.63a1f9a8.js => app.24badece.js} | 4 +- ...\345\215\200\345\241\212\351\217\210.html" | 4 +- ...\351\272\274\346\230\257\351\217\210.html" | 4 +- ...\346\230\257\344\272\244\346\230\223.html" | 4 +- ...\346\211\213\347\272\214\350\262\273.html" | 4 +- .../05-\345\270\263\346\210\266.html" | 4 +- .../06-\347\266\262\350\267\257.html" | 4 +- ...\350\255\230\346\251\237\345\210\266.html" | 4 +- ...\351\207\217\350\255\211\346\230\216.html" | 4 +- ...\347\233\212\350\255\211\346\230\216.html" | 4 +- ...\345\220\214\345\261\244\347\264\232.html" | 4 +- ...\350\211\257\346\217\220\346\241\210.html" | 4 +- ...\346\204\217\350\246\213\347\250\277.html" | 4 +- ...\345\271\243\346\250\231\346\272\226.html" | 4 +- .../14-ERC20\344\276\213\345\255\220.html" | 4 +- ...\357\274\211\346\250\231\346\272\226.html" | 4 +- ...\205\357\274\210metadata\357\274\211.html" | 4 +- ...\350\210\211\346\223\264\345\205\205.html" | 4 +- ...\347\232\204\346\224\271\351\200\262.html" | 4 +- ...0\263\236\346\234\237\347\232\204NFT.html" | 4 +- ...\345\271\243\346\250\231\346\272\226.html" | 4 +- ...\347\232\204\346\241\210\344\276\213.html" | 4 +- ...\350\210\207\350\255\211\346\230\216.html" | 4 +- ...50\247\243\346\236\220Proof-of-Stake.html" | 4 +- ...50\247\243\346\236\220Proof-of-Stake.html" | 4 +- ...50\247\243\346\236\220Proof-of-Stake.html" | 4 +- ...50\247\243\346\236\220Proof-of-Stake.html" | 4 +- ...50\247\243\346\236\220Proof-of-Stake.html" | 4 +- ...50\247\243\346\236\220Proof-of-Stake.html" | 4 +- ...50\247\243\346\236\220Proof-of-Stake.html" | 4 +- .../30-\347\265\220\350\252\236.html" | 4 +- .vuepress/dist/ethereum-101/index.html | 4 +- .../01-\345\211\215\350\250\200.html" | 12 ++++-- .vuepress/dist/head-first-eof/index.html | 42 +++++++++++++++++++ .vuepress/dist/index.html | 4 +- head-first-eof/README.md | 3 ++ 67 files changed, 151 insertions(+), 101 deletions(-) rename .vuepress/dist/assets/js/{23.4ce5df8e.js => 23.fbd9727b.js} (98%) rename .vuepress/dist/assets/js/{24.f6fc25b5.js => 24.d8798d04.js} (98%) rename .vuepress/dist/assets/js/{25.f69d7f61.js => 25.2cda7a07.js} (98%) rename .vuepress/dist/assets/js/{26.1239795f.js => 26.ffa8d039.js} (99%) rename .vuepress/dist/assets/js/{27.c7f13266.js => 27.729b555d.js} (98%) rename .vuepress/dist/assets/js/{28.7490b05b.js => 28.9d532788.js} (98%) rename .vuepress/dist/assets/js/{29.45df8ad8.js => 29.cc51b3c9.js} (97%) rename .vuepress/dist/assets/js/{30.6ae513dc.js => 30.6d713582.js} (97%) rename .vuepress/dist/assets/js/{31.50722645.js => 31.ede9d797.js} (98%) rename .vuepress/dist/assets/js/{32.7d8a5f03.js => 32.2ef16d92.js} (99%) rename .vuepress/dist/assets/js/{33.4a908e19.js => 33.cc69c412.js} (99%) rename .vuepress/dist/assets/js/{35.e73f9098.js => 35.770ffdf6.js} (99%) rename .vuepress/dist/assets/js/{36.dc5f1bb9.js => 36.f857026a.js} (97%) rename .vuepress/dist/assets/js/{37.4f5e73b1.js => 37.ed93802d.js} (98%) rename .vuepress/dist/assets/js/{38.35ee4ee4.js => 38.7d25c164.js} (99%) rename .vuepress/dist/assets/js/{39.1a15401d.js => 39.27a34c86.js} (97%) rename .vuepress/dist/assets/js/{41.dca031ce.js => 41.0145fe58.js} (97%) rename .vuepress/dist/assets/js/{42.4dcfb5f8.js => 42.55c3ac28.js} (99%) rename .vuepress/dist/assets/js/{43.3a95c013.js => 43.dcf8fa43.js} (98%) rename .vuepress/dist/assets/js/{44.6d57de51.js => 44.df717947.js} (98%) rename .vuepress/dist/assets/js/{45.0956e95c.js => 45.7358417c.js} (99%) rename .vuepress/dist/assets/js/{46.7d8be4f3.js => 46.bdb025a8.js} (99%) rename .vuepress/dist/assets/js/{47.a93f348e.js => 47.f895a2cf.js} (99%) rename .vuepress/dist/assets/js/{48.1f5224ec.js => 48.e34e19d6.js} (99%) rename .vuepress/dist/assets/js/{49.5425ea98.js => 49.fe0613a1.js} (99%) rename .vuepress/dist/assets/js/{51.c0c6d69d.js => 51.d6749299.js} (99%) rename .vuepress/dist/assets/js/{52.2ca06770.js => 52.a91199e7.js} (98%) rename .vuepress/dist/assets/js/{53.27e1c49e.js => 53.c312c13b.js} (89%) rename .vuepress/dist/assets/js/{54.978645b9.js => 54.1d257938.js} (98%) create mode 100644 .vuepress/dist/assets/js/55.6f4fc799.js rename .vuepress/dist/assets/js/{app.63a1f9a8.js => app.24badece.js} (74%) create mode 100644 .vuepress/dist/head-first-eof/index.html create mode 100644 head-first-eof/README.md diff --git a/.vuepress/dist/404.html b/.vuepress/dist/404.html index 6a52f94..3990d28 100644 --- a/.vuepress/dist/404.html +++ b/.vuepress/dist/404.html @@ -8,13 +8,13 @@ - +

404

That's a Four-Oh-Four.
Take me home.
- + diff --git a/.vuepress/dist/assets/js/23.4ce5df8e.js b/.vuepress/dist/assets/js/23.fbd9727b.js similarity index 98% rename from .vuepress/dist/assets/js/23.4ce5df8e.js rename to .vuepress/dist/assets/js/23.fbd9727b.js index 1203b77..0e2f789 100644 --- a/.vuepress/dist/assets/js/23.4ce5df8e.js +++ b/.vuepress/dist/assets/js/23.fbd9727b.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{345:function(_,v,t){"use strict";t.r(v);var a=t(17),s=Object(a.a)({},(function(){var _=this,v=_._self._c;return v("ContentSlotsDistributor",{attrs:{"slot-key":_.$parent.slotKey}},[v("h1",{attrs:{id:"什麼是區塊鏈"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#什麼是區塊鏈"}},[_._v("#")]),_._v(" 什麼是區塊鏈?")]),_._v(" "),v("p",[_._v("區塊鏈一直以來都不是一個新的概念,早在西元 1880 年左右就存在了。那時候我們稱之為「麻將」。")]),_._v(" "),v("p",[_._v("什麼?!你說麻將是區塊鏈?")]),_._v(" "),v("p",[_._v("是的,請聽我娓娓道來,不要急著把這網頁關掉呀!(◎_◎;)")]),_._v(" "),v("h2",{attrs:{id:"麻將的過程"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#麻將的過程"}},[_._v("#")]),_._v(" 麻將的過程")]),_._v(" "),v("p",[_._v("我們以四人、十三張麻將為例子來討論:")]),_._v(" "),v("ol",[v("li",[_._v("在開始之前,每位玩家手上都有「籌碼」,且每個玩家可以很清楚知道彼此手上有多少籌碼。")]),_._v(" "),v("li",[_._v("「每一局」在比的是玩家最先在「有限時間內(把牌摸光就結束該局)」找到「特定牌型」即可取得該局的勝利。")]),_._v(" "),v("li",[_._v("有贏家產生的情況,則進行籌碼的轉移。")]),_._v(" "),v("li",[_._v("平局則根據不同規則,決定是否有籌碼轉移後,繼續進行遊戲。")]),_._v(" "),v("li",[_._v("隨著賽局的移動會出現「東、南、西、北風局」與「東、南、西、北坐莊」")])]),_._v(" "),v("h2",{attrs:{id:"以-proof-of-work-為對照來舉例"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#以-proof-of-work-為對照來舉例"}},[_._v("#")]),_._v(" 以 Proof-of-Work 為對照來舉例")]),_._v(" "),v("p",[_._v("等等,所以這跟區塊鏈有什麼關係?")]),_._v(" "),v("ul",[v("li",[_._v("「玩家」:其實就是在區塊鏈上面的「帳戶 (Account)」")]),_._v(" "),v("li",[_._v("「籌碼」:則是帳戶的「餘額 (Balance)」")]),_._v(" "),v("li",[_._v("「每一局」:則是每個「區塊(Block)」")]),_._v(" "),v("li",[_._v("「風局、誰做莊」:其實這個順序就能構成「鏈(Chain)」")]),_._v(" "),v("li",[_._v("「有限時間內找到特定牌型」:這個是「共識機制(Consensus)」")]),_._v(" "),v("li",[_._v("「特定牌型」:實際上就是「雜湊值(Hash)」")])]),_._v(" "),v("p",[_._v("所以換成區塊鏈的情況,就變成了:")]),_._v(" "),v("ol",[v("li",[_._v("在創始之際,有塊「創始區塊(Genesis Block)」,此區塊記錄了每個帳戶的餘額。")]),_._v(" "),v("li",[_._v("在每一輪創建新的區塊的時候,誰會先經過算到「合法的雜湊(Hash)」,且取得「共識」確認得出誰贏得這個區塊,並進入下個區塊的輪次。")]),_._v(" "),v("li",[_._v("贏家可以獲得這個區塊的獎勵。")]),_._v(" "),v("li",[_._v("平局就是繼續直到出塊為止。")])]),_._v(" "),v("h2",{attrs:{id:"區塊鏈的特性"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#區塊鏈的特性"}},[_._v("#")]),_._v(" 區塊鏈的特性")]),_._v(" "),v("p",[_._v("我書讀得少不要騙我,那區塊鏈的「去中心化」、「不可改變」的特性呢?你麻將的例子解釋不了了吧!!!")]),_._v(" "),v("p",[_._v("去中心化,簡言之,便是每個人手上都有一份一樣的資料,可以用來查詢與驗證在區塊鏈上的資訊。不會因為今天無法連上網路或連線受到限制,導致沒網站可以讓你查詢的窘境。\n同理,打麻將的時候,我們總會記住每一家的分數,尤其是過年的時候拿紅包來當籌碼時,特別會去記每個人到底有多少籌碼。不會因為你今天離開那個牌子就忘記籌碼了吧(=゚ω゚)ノ")]),_._v(" "),v("p",[_._v("那不可改變呢?過年打麻將,輸了紅包就噴了,當然不可能是輸家大喊:「我沒有輸!!!」就真的沒輸,其他的玩家肯定會否決這樣的說法,那不就是「不可改變」的特性了嗎?")]),_._v(" "),v("h2",{attrs:{id:"總結"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#總結"}},[_._v("#")]),_._v(" 總結")]),_._v(" "),v("p",[_._v("在本文中是以簡單的例子進行概念上的比較,並不完全精準,只是提供一個思考的方向,讓讀者能更簡單地理解。")]),_._v(" "),v("p",[_._v("如果不知道什麼是區塊鏈,歡迎來找海帶打麻將,你多輸幾場,肯定能用肌肉記憶好好記起來的(´▽`)")]),_._v(" "),v("h2",{attrs:{id:"課後作業"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#課後作業"}},[_._v("#")]),_._v(" 課後作業")]),_._v(" "),v("p",[_._v("實際上在台灣常見的「標會」也可以拿來做 Proof-of-Stake 區塊鏈舉例,那要怎麼對比呢?就請大家回去做功課囉~")])])}),[],!1,null,null,null);v.default=s.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{344:function(_,v,t){"use strict";t.r(v);var a=t(17),s=Object(a.a)({},(function(){var _=this,v=_._self._c;return v("ContentSlotsDistributor",{attrs:{"slot-key":_.$parent.slotKey}},[v("h1",{attrs:{id:"什麼是區塊鏈"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#什麼是區塊鏈"}},[_._v("#")]),_._v(" 什麼是區塊鏈?")]),_._v(" "),v("p",[_._v("區塊鏈一直以來都不是一個新的概念,早在西元 1880 年左右就存在了。那時候我們稱之為「麻將」。")]),_._v(" "),v("p",[_._v("什麼?!你說麻將是區塊鏈?")]),_._v(" "),v("p",[_._v("是的,請聽我娓娓道來,不要急著把這網頁關掉呀!(◎_◎;)")]),_._v(" "),v("h2",{attrs:{id:"麻將的過程"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#麻將的過程"}},[_._v("#")]),_._v(" 麻將的過程")]),_._v(" "),v("p",[_._v("我們以四人、十三張麻將為例子來討論:")]),_._v(" "),v("ol",[v("li",[_._v("在開始之前,每位玩家手上都有「籌碼」,且每個玩家可以很清楚知道彼此手上有多少籌碼。")]),_._v(" "),v("li",[_._v("「每一局」在比的是玩家最先在「有限時間內(把牌摸光就結束該局)」找到「特定牌型」即可取得該局的勝利。")]),_._v(" "),v("li",[_._v("有贏家產生的情況,則進行籌碼的轉移。")]),_._v(" "),v("li",[_._v("平局則根據不同規則,決定是否有籌碼轉移後,繼續進行遊戲。")]),_._v(" "),v("li",[_._v("隨著賽局的移動會出現「東、南、西、北風局」與「東、南、西、北坐莊」")])]),_._v(" "),v("h2",{attrs:{id:"以-proof-of-work-為對照來舉例"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#以-proof-of-work-為對照來舉例"}},[_._v("#")]),_._v(" 以 Proof-of-Work 為對照來舉例")]),_._v(" "),v("p",[_._v("等等,所以這跟區塊鏈有什麼關係?")]),_._v(" "),v("ul",[v("li",[_._v("「玩家」:其實就是在區塊鏈上面的「帳戶 (Account)」")]),_._v(" "),v("li",[_._v("「籌碼」:則是帳戶的「餘額 (Balance)」")]),_._v(" "),v("li",[_._v("「每一局」:則是每個「區塊(Block)」")]),_._v(" "),v("li",[_._v("「風局、誰做莊」:其實這個順序就能構成「鏈(Chain)」")]),_._v(" "),v("li",[_._v("「有限時間內找到特定牌型」:這個是「共識機制(Consensus)」")]),_._v(" "),v("li",[_._v("「特定牌型」:實際上就是「雜湊值(Hash)」")])]),_._v(" "),v("p",[_._v("所以換成區塊鏈的情況,就變成了:")]),_._v(" "),v("ol",[v("li",[_._v("在創始之際,有塊「創始區塊(Genesis Block)」,此區塊記錄了每個帳戶的餘額。")]),_._v(" "),v("li",[_._v("在每一輪創建新的區塊的時候,誰會先經過算到「合法的雜湊(Hash)」,且取得「共識」確認得出誰贏得這個區塊,並進入下個區塊的輪次。")]),_._v(" "),v("li",[_._v("贏家可以獲得這個區塊的獎勵。")]),_._v(" "),v("li",[_._v("平局就是繼續直到出塊為止。")])]),_._v(" "),v("h2",{attrs:{id:"區塊鏈的特性"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#區塊鏈的特性"}},[_._v("#")]),_._v(" 區塊鏈的特性")]),_._v(" "),v("p",[_._v("我書讀得少不要騙我,那區塊鏈的「去中心化」、「不可改變」的特性呢?你麻將的例子解釋不了了吧!!!")]),_._v(" "),v("p",[_._v("去中心化,簡言之,便是每個人手上都有一份一樣的資料,可以用來查詢與驗證在區塊鏈上的資訊。不會因為今天無法連上網路或連線受到限制,導致沒網站可以讓你查詢的窘境。\n同理,打麻將的時候,我們總會記住每一家的分數,尤其是過年的時候拿紅包來當籌碼時,特別會去記每個人到底有多少籌碼。不會因為你今天離開那個牌子就忘記籌碼了吧(=゚ω゚)ノ")]),_._v(" "),v("p",[_._v("那不可改變呢?過年打麻將,輸了紅包就噴了,當然不可能是輸家大喊:「我沒有輸!!!」就真的沒輸,其他的玩家肯定會否決這樣的說法,那不就是「不可改變」的特性了嗎?")]),_._v(" "),v("h2",{attrs:{id:"總結"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#總結"}},[_._v("#")]),_._v(" 總結")]),_._v(" "),v("p",[_._v("在本文中是以簡單的例子進行概念上的比較,並不完全精準,只是提供一個思考的方向,讓讀者能更簡單地理解。")]),_._v(" "),v("p",[_._v("如果不知道什麼是區塊鏈,歡迎來找海帶打麻將,你多輸幾場,肯定能用肌肉記憶好好記起來的(´▽`)")]),_._v(" "),v("h2",{attrs:{id:"課後作業"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#課後作業"}},[_._v("#")]),_._v(" 課後作業")]),_._v(" "),v("p",[_._v("實際上在台灣常見的「標會」也可以拿來做 Proof-of-Stake 區塊鏈舉例,那要怎麼對比呢?就請大家回去做功課囉~")])])}),[],!1,null,null,null);v.default=s.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/24.f6fc25b5.js b/.vuepress/dist/assets/js/24.d8798d04.js similarity index 98% rename from .vuepress/dist/assets/js/24.f6fc25b5.js rename to .vuepress/dist/assets/js/24.d8798d04.js index 0621f7d..80a7e0b 100644 --- a/.vuepress/dist/assets/js/24.f6fc25b5.js +++ b/.vuepress/dist/assets/js/24.d8798d04.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],{349: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/.vuepress/dist/assets/js/25.f69d7f61.js b/.vuepress/dist/assets/js/25.2cda7a07.js similarity index 98% rename from .vuepress/dist/assets/js/25.f69d7f61.js rename to .vuepress/dist/assets/js/25.2cda7a07.js index 0c976e5..8d69307 100644 --- a/.vuepress/dist/assets/js/25.f69d7f61.js +++ b/.vuepress/dist/assets/js/25.2cda7a07.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{344: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],{345: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/.vuepress/dist/assets/js/26.1239795f.js b/.vuepress/dist/assets/js/26.ffa8d039.js similarity index 99% rename from .vuepress/dist/assets/js/26.1239795f.js rename to .vuepress/dist/assets/js/26.ffa8d039.js index 663c323..ef2ac3f 100644 --- a/.vuepress/dist/assets/js/26.1239795f.js +++ b/.vuepress/dist/assets/js/26.ffa8d039.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[26],{352: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],{348: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/.vuepress/dist/assets/js/27.c7f13266.js b/.vuepress/dist/assets/js/27.729b555d.js similarity index 98% rename from .vuepress/dist/assets/js/27.c7f13266.js rename to .vuepress/dist/assets/js/27.729b555d.js index 6cbf8d9..c5442a6 100644 --- a/.vuepress/dist/assets/js/27.c7f13266.js +++ b/.vuepress/dist/assets/js/27.729b555d.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[27],{347: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],{346: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/.vuepress/dist/assets/js/28.7490b05b.js b/.vuepress/dist/assets/js/28.9d532788.js similarity index 98% rename from .vuepress/dist/assets/js/28.7490b05b.js rename to .vuepress/dist/assets/js/28.9d532788.js index 83d7357..9468d77 100644 --- a/.vuepress/dist/assets/js/28.7490b05b.js +++ b/.vuepress/dist/assets/js/28.9d532788.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[28],{348:function(t,e,r){"use strict";r.r(e);var a=r(17),_=Object(a.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"網路-network"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#網路-network"}},[t._v("#")]),t._v(" 網路(Network)")]),t._v(" "),e("p",[t._v("網路,不是我們上網的含義,而是由多個「節點(Node)」所組成的網路,也就是以太坊根據不同目的所組成的環境。專門用來讓不同層級的開發者與使用者進行「開發」、「測試」、「生產」的不同階段所使用。")]),t._v(" "),e("h2",{attrs:{id:"鏈-id-chain-id"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#鏈-id-chain-id"}},[t._v("#")]),t._v(" 鏈 ID (Chain ID)")]),t._v(" "),e("p",[t._v("在以太坊上,鏈 ID 等同於網路 ID (Network ID)。因此以下都只討論鏈 ID 。")]),t._v(" "),e("p",[t._v("由於有不同的網路存在,為了讓使用者更好的區分環境,因此每個網路都有其獨特的 ID。")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("網路名稱")]),t._v(" "),e("th",[t._v("鏈 ID")]),t._v(" "),e("th",[t._v("目的")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[t._v("主網(Mainnet)")]),t._v(" "),e("td",[t._v("1")]),t._v(" "),e("td",[t._v("生產環境")])]),t._v(" "),e("tr",[e("td",[t._v("Goerli 測試網(Goerli Testnet)")]),t._v(" "),e("td",[t._v("5")]),t._v(" "),e("td",[t._v("測試環境")])]),t._v(" "),e("tr",[e("td",[t._v("Sepolia 測試網(Sepolia Testnet)")]),t._v(" "),e("td",[t._v("11155111")]),t._v(" "),e("td",[t._v("測試環境")])])])]),t._v(" "),e("h2",{attrs:{id:"主網-mainnet"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#主網-mainnet"}},[t._v("#")]),t._v(" 主網(Mainnet)")]),t._v(" "),e("p",[t._v("為以太坊的正式網路,切記,所有發生在此網路上的交易才是真實的交易。在測試網路上的交易通常是完全無價值的。包含:Ether 幣價、ERC20 Token 的交易、NFT 的交易等等。")]),t._v(" "),e("h2",{attrs:{id:"測試網-testnet"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#測試網-testnet"}},[t._v("#")]),t._v(" 測試網(Testnet)")]),t._v(" "),e("p",[t._v("測試,是一件很重要的事情。千萬不要在生產(Production)環境裡面直接部署任何東西,而為了讓開發者們有測試的環境,以太坊便提供了多個不同的網路。")]),t._v(" "),e("h3",{attrs:{id:"goerli-測試網"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#goerli-測試網"}},[t._v("#")]),t._v(" Goerli 測試網")]),t._v(" "),e("p",[t._v("Goerli 測試網使用權益證明(Proof-of-stake)的共識機制產生區塊。\n不像某些短期用途的測試網,Goerli 是一個被保證會長期營運的穩定測試網,所以智能合約的開發者可以放心的在上面部署應用,且也由於這個特性,目前在主網上很多應用生態在這個測試網上都有一份以供開發者們串接。")]),t._v(" "),e("p",[t._v("此外,在 The Merge 測試後 Goerli 測試網已經開放「任何人」質押 ETH 成為驗證者。")]),t._v(" "),e("h4",{attrs:{id:"goerli-相關連結"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#goerli-相關連結"}},[t._v("#")]),t._v(" Goerli 相關連結")]),t._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"https://goerli.net/",target:"_blank",rel:"noopener noreferrer"}},[t._v("官網"),e("OutboundLink")],1)]),t._v(" "),e("li",[e("a",{attrs:{href:"https://goerli.etherscan.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Etherscan 瀏覽器"),e("OutboundLink")],1)]),t._v(" "),e("li",[e("a",{attrs:{href:"https://goerli-faucet.mudit.blog/",target:"_blank",rel:"noopener noreferrer"}},[t._v("水龍頭"),e("OutboundLink")],1)])]),t._v(" "),e("h3",{attrs:{id:"sepolia-測試網"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#sepolia-測試網"}},[t._v("#")]),t._v(" Sepolia 測試網")]),t._v(" "),e("p",[t._v("Sepolia 測試網也是使用權益證明(Proof-of-stake)作為共識機制。然而這個測試網當時的目的是為了 The Merge 的升級測試所使用,算是較新的測試網。")]),t._v(" "),e("p",[t._v("此外,在 The Merge 測試後,Sepolia 並只開放給特定人士參與質押 ETH 成為驗證者。")]),t._v(" "),e("h4",{attrs:{id:"sepolia-相關連結"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#sepolia-相關連結"}},[t._v("#")]),t._v(" Sepolia 相關連結")]),t._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"https://sepolia.dev/",target:"_blank",rel:"noopener noreferrer"}},[t._v("官網"),e("OutboundLink")],1)]),t._v(" "),e("li",[e("a",{attrs:{href:"https://sepolia.etherscan.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Etherscan 瀏覽器"),e("OutboundLink")],1)]),t._v(" "),e("li",[e("a",{attrs:{href:"https://faucet.sepolia.dev/",target:"_blank",rel:"noopener noreferrer"}},[t._v("水龍頭"),e("OutboundLink")],1)])]),t._v(" "),e("h3",{attrs:{id:"那些已經被關掉的測試網"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#那些已經被關掉的測試網"}},[t._v("#")]),t._v(" 那些已經被關掉的測試網")]),t._v(" "),e("p",[t._v("曾經我也部署合約在上面過,現在,請讓我們懷念他們的逝去。")]),t._v(" "),e("ul",[e("li",[t._v("Ropsten")]),t._v(" "),e("li",[t._v("Rinkeby")]),t._v(" "),e("li",[t._v("Kovan")])])])}),[],!1,null,null,null);e.default=_.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[28],{347:function(t,e,r){"use strict";r.r(e);var a=r(17),_=Object(a.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"網路-network"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#網路-network"}},[t._v("#")]),t._v(" 網路(Network)")]),t._v(" "),e("p",[t._v("網路,不是我們上網的含義,而是由多個「節點(Node)」所組成的網路,也就是以太坊根據不同目的所組成的環境。專門用來讓不同層級的開發者與使用者進行「開發」、「測試」、「生產」的不同階段所使用。")]),t._v(" "),e("h2",{attrs:{id:"鏈-id-chain-id"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#鏈-id-chain-id"}},[t._v("#")]),t._v(" 鏈 ID (Chain ID)")]),t._v(" "),e("p",[t._v("在以太坊上,鏈 ID 等同於網路 ID (Network ID)。因此以下都只討論鏈 ID 。")]),t._v(" "),e("p",[t._v("由於有不同的網路存在,為了讓使用者更好的區分環境,因此每個網路都有其獨特的 ID。")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("網路名稱")]),t._v(" "),e("th",[t._v("鏈 ID")]),t._v(" "),e("th",[t._v("目的")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[t._v("主網(Mainnet)")]),t._v(" "),e("td",[t._v("1")]),t._v(" "),e("td",[t._v("生產環境")])]),t._v(" "),e("tr",[e("td",[t._v("Goerli 測試網(Goerli Testnet)")]),t._v(" "),e("td",[t._v("5")]),t._v(" "),e("td",[t._v("測試環境")])]),t._v(" "),e("tr",[e("td",[t._v("Sepolia 測試網(Sepolia Testnet)")]),t._v(" "),e("td",[t._v("11155111")]),t._v(" "),e("td",[t._v("測試環境")])])])]),t._v(" "),e("h2",{attrs:{id:"主網-mainnet"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#主網-mainnet"}},[t._v("#")]),t._v(" 主網(Mainnet)")]),t._v(" "),e("p",[t._v("為以太坊的正式網路,切記,所有發生在此網路上的交易才是真實的交易。在測試網路上的交易通常是完全無價值的。包含:Ether 幣價、ERC20 Token 的交易、NFT 的交易等等。")]),t._v(" "),e("h2",{attrs:{id:"測試網-testnet"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#測試網-testnet"}},[t._v("#")]),t._v(" 測試網(Testnet)")]),t._v(" "),e("p",[t._v("測試,是一件很重要的事情。千萬不要在生產(Production)環境裡面直接部署任何東西,而為了讓開發者們有測試的環境,以太坊便提供了多個不同的網路。")]),t._v(" "),e("h3",{attrs:{id:"goerli-測試網"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#goerli-測試網"}},[t._v("#")]),t._v(" Goerli 測試網")]),t._v(" "),e("p",[t._v("Goerli 測試網使用權益證明(Proof-of-stake)的共識機制產生區塊。\n不像某些短期用途的測試網,Goerli 是一個被保證會長期營運的穩定測試網,所以智能合約的開發者可以放心的在上面部署應用,且也由於這個特性,目前在主網上很多應用生態在這個測試網上都有一份以供開發者們串接。")]),t._v(" "),e("p",[t._v("此外,在 The Merge 測試後 Goerli 測試網已經開放「任何人」質押 ETH 成為驗證者。")]),t._v(" "),e("h4",{attrs:{id:"goerli-相關連結"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#goerli-相關連結"}},[t._v("#")]),t._v(" Goerli 相關連結")]),t._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"https://goerli.net/",target:"_blank",rel:"noopener noreferrer"}},[t._v("官網"),e("OutboundLink")],1)]),t._v(" "),e("li",[e("a",{attrs:{href:"https://goerli.etherscan.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Etherscan 瀏覽器"),e("OutboundLink")],1)]),t._v(" "),e("li",[e("a",{attrs:{href:"https://goerli-faucet.mudit.blog/",target:"_blank",rel:"noopener noreferrer"}},[t._v("水龍頭"),e("OutboundLink")],1)])]),t._v(" "),e("h3",{attrs:{id:"sepolia-測試網"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#sepolia-測試網"}},[t._v("#")]),t._v(" Sepolia 測試網")]),t._v(" "),e("p",[t._v("Sepolia 測試網也是使用權益證明(Proof-of-stake)作為共識機制。然而這個測試網當時的目的是為了 The Merge 的升級測試所使用,算是較新的測試網。")]),t._v(" "),e("p",[t._v("此外,在 The Merge 測試後,Sepolia 並只開放給特定人士參與質押 ETH 成為驗證者。")]),t._v(" "),e("h4",{attrs:{id:"sepolia-相關連結"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#sepolia-相關連結"}},[t._v("#")]),t._v(" Sepolia 相關連結")]),t._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"https://sepolia.dev/",target:"_blank",rel:"noopener noreferrer"}},[t._v("官網"),e("OutboundLink")],1)]),t._v(" "),e("li",[e("a",{attrs:{href:"https://sepolia.etherscan.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Etherscan 瀏覽器"),e("OutboundLink")],1)]),t._v(" "),e("li",[e("a",{attrs:{href:"https://faucet.sepolia.dev/",target:"_blank",rel:"noopener noreferrer"}},[t._v("水龍頭"),e("OutboundLink")],1)])]),t._v(" "),e("h3",{attrs:{id:"那些已經被關掉的測試網"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#那些已經被關掉的測試網"}},[t._v("#")]),t._v(" 那些已經被關掉的測試網")]),t._v(" "),e("p",[t._v("曾經我也部署合約在上面過,現在,請讓我們懷念他們的逝去。")]),t._v(" "),e("ul",[e("li",[t._v("Ropsten")]),t._v(" "),e("li",[t._v("Rinkeby")]),t._v(" "),e("li",[t._v("Kovan")])])])}),[],!1,null,null,null);e.default=_.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/29.45df8ad8.js b/.vuepress/dist/assets/js/29.cc51b3c9.js similarity index 97% rename from .vuepress/dist/assets/js/29.45df8ad8.js rename to .vuepress/dist/assets/js/29.cc51b3c9.js index 5969f03..b47008c 100644 --- a/.vuepress/dist/assets/js/29.45df8ad8.js +++ b/.vuepress/dist/assets/js/29.cc51b3c9.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[29],{349: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/.vuepress/dist/assets/js/30.6ae513dc.js b/.vuepress/dist/assets/js/30.6d713582.js similarity index 97% rename from .vuepress/dist/assets/js/30.6ae513dc.js rename to .vuepress/dist/assets/js/30.6d713582.js index e8d0140..152a903 100644 --- a/.vuepress/dist/assets/js/30.6ae513dc.js +++ b/.vuepress/dist/assets/js/30.6d713582.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{350:function(t,a,r){"use strict";r.r(a);var o=r(17),s=Object(o.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"工作量證明-proof-of-work"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#工作量證明-proof-of-work"}},[t._v("#")]),t._v(" 工作量證明(Proof-of-Work)")]),t._v(" "),a("p",[t._v("設定一個作業,讓所有參與的人提出自己解作業的證明,這個解作業的過程便是所謂的工作量,最終最先解出來的人就是贏家,可以獲得該區塊的記帳權。")]),t._v(" "),a("h2",{attrs:{id:"就是挖礦囉"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#就是挖礦囉"}},[t._v("#")]),t._v(" 就是挖礦囉?")]),t._v(" "),a("p",[t._v("PoW 基本上是一個計算雜湊值的小遊戲,每一回合(產生區塊的區間)都會設定一個難度(difficulty),當有人在特定的難度下解出符合規則的答案就獲勝取得獎勵,很像是花了巨大的勞力在挖礦,突然間挖出黃金的概念。因此我們稱參與工作量證明的人為「礦工」,而參與工作量證明這件事為「挖礦」。")]),t._v(" "),a("h2",{attrs:{id:"為什麼-pow-挖礦很耗電"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#為什麼-pow-挖礦很耗電"}},[t._v("#")]),t._v(" 為什麼 PoW 挖礦很耗電")]),t._v(" "),a("p",[t._v("因為計算雜湊這件事本身除了算出來以外,沒有任何其他的意義。\n但計算的過程卻是需要花很大的力氣在上面,尤其在越多礦工存在的情況,你需要花費更多的成本添購機器,花費更多的電力來供應給這些機器,想像一下你的電腦以 100% 的使用率完全不關機執行的電費,就知道這件事有多麽耗能。")]),t._v(" "),a("h2",{attrs:{id:"如何參與到-pow-挖礦"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#如何參與到-pow-挖礦"}},[t._v("#")]),t._v(" 如何參與到 PoW 挖礦")]),t._v(" "),a("p",[t._v("很抱歉,你沒辦法參與了╮(╯▽╰)╭\n在 The Merge 以後,以太坊不再採用 PoW 作為他的共識機制,因此不再有機會參與 PoW 挖礦了。")]),t._v(" "),a("p",[t._v("但有個好消息是,你可以改參與權益證明(Proof-of-Stake)的挖礦,只需要你去質押 ETH 與執行節點就能參與喔!")]),t._v(" "),a("h2",{attrs:{id:"結語"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#結語"}},[t._v("#")]),t._v(" 結語")]),t._v(" "),a("p",[t._v("拋棄 PoW 是個好趨勢,因為不再需要倚賴算力,因此更省電了,北極熊表示感謝。\n而對於想做 AI 應用與遊戲玩家而言更是一件好事,看看精美的顯示卡跳水價格,我們終於能在正常的價格買到該有的品質了。")]),t._v(" "),a("p",[t._v("真是可喜可賀、可喜可賀!")])])}),[],!1,null,null,null);a.default=s.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{351:function(t,a,r){"use strict";r.r(a);var o=r(17),s=Object(o.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"工作量證明-proof-of-work"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#工作量證明-proof-of-work"}},[t._v("#")]),t._v(" 工作量證明(Proof-of-Work)")]),t._v(" "),a("p",[t._v("設定一個作業,讓所有參與的人提出自己解作業的證明,這個解作業的過程便是所謂的工作量,最終最先解出來的人就是贏家,可以獲得該區塊的記帳權。")]),t._v(" "),a("h2",{attrs:{id:"就是挖礦囉"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#就是挖礦囉"}},[t._v("#")]),t._v(" 就是挖礦囉?")]),t._v(" "),a("p",[t._v("PoW 基本上是一個計算雜湊值的小遊戲,每一回合(產生區塊的區間)都會設定一個難度(difficulty),當有人在特定的難度下解出符合規則的答案就獲勝取得獎勵,很像是花了巨大的勞力在挖礦,突然間挖出黃金的概念。因此我們稱參與工作量證明的人為「礦工」,而參與工作量證明這件事為「挖礦」。")]),t._v(" "),a("h2",{attrs:{id:"為什麼-pow-挖礦很耗電"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#為什麼-pow-挖礦很耗電"}},[t._v("#")]),t._v(" 為什麼 PoW 挖礦很耗電")]),t._v(" "),a("p",[t._v("因為計算雜湊這件事本身除了算出來以外,沒有任何其他的意義。\n但計算的過程卻是需要花很大的力氣在上面,尤其在越多礦工存在的情況,你需要花費更多的成本添購機器,花費更多的電力來供應給這些機器,想像一下你的電腦以 100% 的使用率完全不關機執行的電費,就知道這件事有多麽耗能。")]),t._v(" "),a("h2",{attrs:{id:"如何參與到-pow-挖礦"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#如何參與到-pow-挖礦"}},[t._v("#")]),t._v(" 如何參與到 PoW 挖礦")]),t._v(" "),a("p",[t._v("很抱歉,你沒辦法參與了╮(╯▽╰)╭\n在 The Merge 以後,以太坊不再採用 PoW 作為他的共識機制,因此不再有機會參與 PoW 挖礦了。")]),t._v(" "),a("p",[t._v("但有個好消息是,你可以改參與權益證明(Proof-of-Stake)的挖礦,只需要你去質押 ETH 與執行節點就能參與喔!")]),t._v(" "),a("h2",{attrs:{id:"結語"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#結語"}},[t._v("#")]),t._v(" 結語")]),t._v(" "),a("p",[t._v("拋棄 PoW 是個好趨勢,因為不再需要倚賴算力,因此更省電了,北極熊表示感謝。\n而對於想做 AI 應用與遊戲玩家而言更是一件好事,看看精美的顯示卡跳水價格,我們終於能在正常的價格買到該有的品質了。")]),t._v(" "),a("p",[t._v("真是可喜可賀、可喜可賀!")])])}),[],!1,null,null,null);a.default=s.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/31.50722645.js b/.vuepress/dist/assets/js/31.ede9d797.js similarity index 98% rename from .vuepress/dist/assets/js/31.50722645.js rename to .vuepress/dist/assets/js/31.ede9d797.js index ae6440c..175d62e 100644 --- a/.vuepress/dist/assets/js/31.50722645.js +++ b/.vuepress/dist/assets/js/31.ede9d797.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[31],{351:function(t,v,_){"use strict";_.r(v);var a=_(17),o=Object(a.a)({},(function(){var t=this,v=t._self._c;return v("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[v("h1",{attrs:{id:"權益證明-proof-of-stake"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#權益證明-proof-of-stake"}},[t._v("#")]),t._v(" 權益證明(Proof-of-Stake)")]),t._v(" "),v("p",[v("img",{attrs:{src:"https://i.imgur.com/lW0lyVo.png",alt:""}})]),t._v(" "),v("h2",{attrs:{id:"什麼是權益證明"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#什麼是權益證明"}},[t._v("#")]),t._v(" 什麼是權益證明")]),t._v(" "),v("p",[t._v("不同於工作量證明需要礦工花費大量的電力(與礦機成本)來進行計算雜湊值的遊戲。權益證明只需要一台簡單的電腦,執行節點,並把 ETH 質押進以太坊上的一個智能合約中,就可以成為驗證者。")]),t._v(" "),v("p",[t._v("現在不再需要礦工,而是由驗證者負責去檢查區塊的正確性,若驗證者為人正直,檢查都沒問題就會得到獎勵;反之,作惡的驗證者將會被沒入之前質押的 ETH 作為懲罰。")]),t._v(" "),v("h2",{attrs:{id:"如何成為驗證者"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#如何成為驗證者"}},[t._v("#")]),t._v(" 如何成為驗證者")]),t._v(" "),v("p",[t._v("想加入驗證者的行列,你不用骨骼驚奇,也不用身體異於常人。你只需要準備 32 顆 ETH(可以直接跟人買),並把這些 ETH 存入合約中,且在你的電腦上執行以下三個軟體:")]),t._v(" "),v("ol",[v("li",[t._v("執行客戶端(Execution Client)")]),t._v(" "),v("li",[t._v("共識客戶端(Consensus Client)")]),t._v(" "),v("li",[t._v("驗證者客戶端(Validator)")])]),t._v(" "),v("p",[t._v("為了避免驗證者可以瞬間大量加入或大量退出,以太坊的 PoS 有限制加入的等待期與退出的冷卻期。一但把 ETH 存入,會先被加入一個隊列中,等待你的節點被正式啟用。")]),t._v(" "),v("h2",{attrs:{id:"驗證者應該做什麼"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#驗證者應該做什麼"}},[t._v("#")]),t._v(" 驗證者應該做什麼")]),t._v(" "),v("p",[t._v("一但啟用成功,驗證者就會從以太坊網路的其他節點接收到新區塊。接著驗證者必須負起責任將區塊中的所有交易依序執行,並檢查區塊的簽名(Signature)是否合法。在這些檢查都完成以後,驗證者需要發出一個投票(在以太坊有個專業術語 "),v("code",[t._v("attestation")]),t._v(")。")]),t._v(" "),v("p",[t._v("在 PoS 中,每一輪次的驗證都是有嚴格定義的:")]),t._v(" "),v("ol",[v("li",[t._v("每一個紀元/週期("),v("code",[t._v("epoch")]),t._v(")包含了 32 個槽("),v("code",[t._v("slot")]),t._v(")")]),t._v(" "),v("li",[t._v("每個槽為 12 秒")])]),t._v(" "),v("p",[t._v("在每個槽中:")]),t._v(" "),v("ol",[v("li",[t._v("將有一位驗證者會被隨機選到成為區塊的提議者("),v("code",[t._v("block proposer")]),t._v("),被選中的驗證者必須負責建立新的區塊,並把這個新區塊發送給其他節點。")]),t._v(" "),v("li",[t._v("同時會有一群驗證者會被隨機選為「委員會(committee)」,這個委員會必須負責投票與驗證被提議者提出的新區塊。")])])])}),[],!1,null,null,null);v.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[31],{354:function(t,v,_){"use strict";_.r(v);var a=_(17),o=Object(a.a)({},(function(){var t=this,v=t._self._c;return v("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[v("h1",{attrs:{id:"權益證明-proof-of-stake"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#權益證明-proof-of-stake"}},[t._v("#")]),t._v(" 權益證明(Proof-of-Stake)")]),t._v(" "),v("p",[v("img",{attrs:{src:"https://i.imgur.com/lW0lyVo.png",alt:""}})]),t._v(" "),v("h2",{attrs:{id:"什麼是權益證明"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#什麼是權益證明"}},[t._v("#")]),t._v(" 什麼是權益證明")]),t._v(" "),v("p",[t._v("不同於工作量證明需要礦工花費大量的電力(與礦機成本)來進行計算雜湊值的遊戲。權益證明只需要一台簡單的電腦,執行節點,並把 ETH 質押進以太坊上的一個智能合約中,就可以成為驗證者。")]),t._v(" "),v("p",[t._v("現在不再需要礦工,而是由驗證者負責去檢查區塊的正確性,若驗證者為人正直,檢查都沒問題就會得到獎勵;反之,作惡的驗證者將會被沒入之前質押的 ETH 作為懲罰。")]),t._v(" "),v("h2",{attrs:{id:"如何成為驗證者"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#如何成為驗證者"}},[t._v("#")]),t._v(" 如何成為驗證者")]),t._v(" "),v("p",[t._v("想加入驗證者的行列,你不用骨骼驚奇,也不用身體異於常人。你只需要準備 32 顆 ETH(可以直接跟人買),並把這些 ETH 存入合約中,且在你的電腦上執行以下三個軟體:")]),t._v(" "),v("ol",[v("li",[t._v("執行客戶端(Execution Client)")]),t._v(" "),v("li",[t._v("共識客戶端(Consensus Client)")]),t._v(" "),v("li",[t._v("驗證者客戶端(Validator)")])]),t._v(" "),v("p",[t._v("為了避免驗證者可以瞬間大量加入或大量退出,以太坊的 PoS 有限制加入的等待期與退出的冷卻期。一但把 ETH 存入,會先被加入一個隊列中,等待你的節點被正式啟用。")]),t._v(" "),v("h2",{attrs:{id:"驗證者應該做什麼"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#驗證者應該做什麼"}},[t._v("#")]),t._v(" 驗證者應該做什麼")]),t._v(" "),v("p",[t._v("一但啟用成功,驗證者就會從以太坊網路的其他節點接收到新區塊。接著驗證者必須負起責任將區塊中的所有交易依序執行,並檢查區塊的簽名(Signature)是否合法。在這些檢查都完成以後,驗證者需要發出一個投票(在以太坊有個專業術語 "),v("code",[t._v("attestation")]),t._v(")。")]),t._v(" "),v("p",[t._v("在 PoS 中,每一輪次的驗證都是有嚴格定義的:")]),t._v(" "),v("ol",[v("li",[t._v("每一個紀元/週期("),v("code",[t._v("epoch")]),t._v(")包含了 32 個槽("),v("code",[t._v("slot")]),t._v(")")]),t._v(" "),v("li",[t._v("每個槽為 12 秒")])]),t._v(" "),v("p",[t._v("在每個槽中:")]),t._v(" "),v("ol",[v("li",[t._v("將有一位驗證者會被隨機選到成為區塊的提議者("),v("code",[t._v("block proposer")]),t._v("),被選中的驗證者必須負責建立新的區塊,並把這個新區塊發送給其他節點。")]),t._v(" "),v("li",[t._v("同時會有一群驗證者會被隨機選為「委員會(committee)」,這個委員會必須負責投票與驗證被提議者提出的新區塊。")])])])}),[],!1,null,null,null);v.default=o.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/32.7d8a5f03.js b/.vuepress/dist/assets/js/32.2ef16d92.js similarity index 99% rename from .vuepress/dist/assets/js/32.7d8a5f03.js rename to .vuepress/dist/assets/js/32.2ef16d92.js index f33c3a5..28730aa 100644 --- a/.vuepress/dist/assets/js/32.7d8a5f03.js +++ b/.vuepress/dist/assets/js/32.2ef16d92.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[32],{353:function(e,t,v){"use strict";v.r(t);var a=v(17),r=Object(a.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"以太坊生態系的不同層級"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#以太坊生態系的不同層級"}},[e._v("#")]),e._v(" 以太坊生態系的不同層級")]),e._v(" "),t("p",[e._v("本篇文章的五層分級概念來自以太坊官網上的 "),t("a",{attrs:{href:"https://ethereum.org/en/developers/docs/ethereum-stack/",target:"_blank",rel:"noopener noreferrer"}},[e._v("INTRODUCTION TO THE ETHEREUM STACK"),t("OutboundLink")],1),e._v(" 文章。")]),e._v(" "),t("h2",{attrs:{id:"層級"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#層級"}},[e._v("#")]),e._v(" 層級")]),e._v(" "),t("p",[e._v("以太坊是個巨大的生態系,而構築一個生態系必然不只能存在一個特定的層級,而需要多個不同層級的開發者與使用者的參與,才能讓整個生態欣欣向榮。本篇文章就是要介紹這些不同層級的角色,與他們之間在意的點。")]),e._v(" "),t("h3",{attrs:{id:"level-0-共識層-consensus-layer"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#level-0-共識層-consensus-layer"}},[e._v("#")]),e._v(" Level 0: 共識層 Consensus Layer")]),e._v(" "),t("p",[e._v("雖然在以太坊的文章中,並沒有提到共識層,但我認為這是一切的核心基礎,有個好個共識層與其對應的激勵機制,才能讓礦工/驗證者留下來支撐這個生態,才能讓整個網路有了安全的基礎。")]),e._v(" "),t("p",[e._v("在這個層級裡,通常都是最底層的共識演算法的開發者,他們專注在解決共識演算法中的細節,包含但不限於:")]),e._v(" "),t("ol",[t("li",[e._v("設計良好的激勵機制")]),e._v(" "),t("li",[e._v("設計嚴格的懲罰機制")]),e._v(" "),t("li",[e._v("對安全性的評估等等")])]),e._v(" "),t("p",[e._v("由於需要的專業知識較深,因此比較屬於研究者的領域,普通的區塊鏈使用者或者 DApp 的開發者並不會對這方面有太多的著墨。")]),e._v(" "),t("h3",{attrs:{id:"level-1-以太坊虛擬機-ethereum-virtual-machine"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#level-1-以太坊虛擬機-ethereum-virtual-machine"}},[e._v("#")]),e._v(" Level 1: 以太坊虛擬機 Ethereum Virtual Machine")]),e._v(" "),t("p",[e._v("除了共識層之外,以太坊與比特幣最大的差異在於以太坊有著良好的智能合約執行環境。")]),e._v(" "),t("p",[e._v("以太坊虛擬機是執行一切交易的核心,從轉帳、部署合約、與合約互動等,無處不是它的範疇。它就像是你最忠實的手機默默地幫你執行所需要的 App。")]),e._v(" "),t("p",[e._v("作為使用者當然是不需要知道以太坊虛擬機是怎麼執行的,甚至不需要知道有以太坊虛擬機的角色存在。然而,與參考文內的說法不同,我認為至少智能合約的開發者需要深入理解以太坊虛擬機的指令,理解越深,越能寫出更省燃料,更精巧的合約。")]),e._v(" "),t("h3",{attrs:{id:"level-2-智能合約-smart-contract"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#level-2-智能合約-smart-contract"}},[e._v("#")]),e._v(" Level 2: 智能合約 Smart Contract")]),e._v(" "),t("p",[e._v("到這裡就是大家常說的 Web 3.0 的開發者了,開發者們會通過撰寫智能合約的程式語言,將商業邏輯部署在以太坊上。")]),e._v(" "),t("p",[e._v("即使到了智能合約的層級,使用者依然不需要對此層級有什麼了解,因為很多合約不一定是開放原始碼的,既然看不見,那只能從開發者提供的公開介面去做互動,相對受限。")]),e._v(" "),t("p",[e._v("而作為 DApp 的開發者,這層級開始就是他們吃飯的根據。他們需要熟悉所有智能合約語言與以太坊的特性,這也是許多應用生態系的所在,比如說穩定幣(Stable Coin)、去中心化交易所(Decentralized Exchange)等都是在這個層級被開發出來的。")]),e._v(" "),t("h3",{attrs:{id:"level-3-以太坊節點-ethereum-nodes"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#level-3-以太坊節點-ethereum-nodes"}},[e._v("#")]),e._v(" Level 3: 以太坊節點 Ethereum Nodes")]),e._v(" "),t("p",[e._v("這裡就是使用者們能與以太坊網路上的應用互動的最低層級,通過節點,我們可以存取在區塊鏈上的資料、發送交易到網路上。")]),e._v(" "),t("p",[e._v("除此之外,也是驗證者參與的層級,他們通過執行節點與驗證者軟體,驗證區塊上每筆交易的正確性,來確保了整個網路的安全與資料的精準度。他們也承載著整個區塊鏈網路的資料(是的,所有的網路狀態都會存在節點中)。")]),e._v(" "),t("p",[e._v("而節點也提供了最低層級的 JSON-RPC API ,讓應用程式可以與節點互動,這些 API 包含但不限於:")]),e._v(" "),t("ol",[t("li",[e._v("讀取區塊鏈上的資料,如:使用者帳戶的餘額")]),e._v(" "),t("li",[e._v("發送交易到網路上,如:轉帳、部署合約、與合約互動")])]),e._v(" "),t("h3",{attrs:{id:"level-4-以太坊客戶端-apis-ethereum-client-apis"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#level-4-以太坊客戶端-apis-ethereum-client-apis"}},[e._v("#")]),e._v(" Level 4: 以太坊客戶端 APIs Ethereum Client APIs")]),e._v(" "),t("p",[e._v("直接與以太坊節點互動雖然暴力但簡單有效,但每次都要手動操作底層 JSON-RPC 的 API 實在不甚方便。")]),e._v(" "),t("p",[e._v("為了方便開發者與使用者與節點互動,在節點之上包裝了一層客戶端,將各種方便的函式庫封裝好,以達到更簡潔與便利的操作。")]),e._v(" "),t("p",[e._v("以網頁軟體為例,使用 JavaScript API ,如 ether.js 的函式庫來與客戶端互動。若是在伺服器端上的軟體,也能使用 Python 或 Java API 來互動。")]),e._v(" "),t("p",[e._v("這些 API 建構了很多好用的輪子,讓開發者與使用者能從走路變成騎車,節省很多重複的操作,比如 ETH、Gwei、Wei 間的單位轉換等這類常用但 JSON-RPC API 不提供的功能;又比如把合約的介面做了簡單的封裝,能更直覺地操作合約內的函式與資料。")]),e._v(" "),t("h3",{attrs:{id:"level-5-終端使用者的應用層-end-user-applications"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#level-5-終端使用者的應用層-end-user-applications"}},[e._v("#")]),e._v(" Level 5: 終端使用者的應用層 End-User Applications")]),e._v(" "),t("p",[e._v("在這裡便是大眾使用者參與的層級,他們不需要知道以太坊虛擬機、不用理解智能合約、不需要關注以太坊節點、也不用操作以太坊客戶端 API、甚至不需要知道這個網站或者軟體的背後是不是使用區塊鏈技術。")]),e._v(" "),t("p",[e._v("當這件事發生的時候,我認為才是區塊鏈真的走進大眾的眼裡,如同在銀行匯款轉帳時,我們不曾去思考過銀行怎麼儲存貨幣;在買賣股票時,不需要知道內部的撮合演算法與股票紀錄的方式。一切就是對介面的操作,就這麼簡單。")]),e._v(" "),t("p",[e._v("在這層級解決了特定的痛點與問題,但不需要讓使用者知道這背後是區塊鏈。而這,也是我對區塊鏈應用的未來想像,也是現在從業人員的終極目標。")])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[32],{352:function(e,t,v){"use strict";v.r(t);var a=v(17),r=Object(a.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"以太坊生態系的不同層級"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#以太坊生態系的不同層級"}},[e._v("#")]),e._v(" 以太坊生態系的不同層級")]),e._v(" "),t("p",[e._v("本篇文章的五層分級概念來自以太坊官網上的 "),t("a",{attrs:{href:"https://ethereum.org/en/developers/docs/ethereum-stack/",target:"_blank",rel:"noopener noreferrer"}},[e._v("INTRODUCTION TO THE ETHEREUM STACK"),t("OutboundLink")],1),e._v(" 文章。")]),e._v(" "),t("h2",{attrs:{id:"層級"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#層級"}},[e._v("#")]),e._v(" 層級")]),e._v(" "),t("p",[e._v("以太坊是個巨大的生態系,而構築一個生態系必然不只能存在一個特定的層級,而需要多個不同層級的開發者與使用者的參與,才能讓整個生態欣欣向榮。本篇文章就是要介紹這些不同層級的角色,與他們之間在意的點。")]),e._v(" "),t("h3",{attrs:{id:"level-0-共識層-consensus-layer"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#level-0-共識層-consensus-layer"}},[e._v("#")]),e._v(" Level 0: 共識層 Consensus Layer")]),e._v(" "),t("p",[e._v("雖然在以太坊的文章中,並沒有提到共識層,但我認為這是一切的核心基礎,有個好個共識層與其對應的激勵機制,才能讓礦工/驗證者留下來支撐這個生態,才能讓整個網路有了安全的基礎。")]),e._v(" "),t("p",[e._v("在這個層級裡,通常都是最底層的共識演算法的開發者,他們專注在解決共識演算法中的細節,包含但不限於:")]),e._v(" "),t("ol",[t("li",[e._v("設計良好的激勵機制")]),e._v(" "),t("li",[e._v("設計嚴格的懲罰機制")]),e._v(" "),t("li",[e._v("對安全性的評估等等")])]),e._v(" "),t("p",[e._v("由於需要的專業知識較深,因此比較屬於研究者的領域,普通的區塊鏈使用者或者 DApp 的開發者並不會對這方面有太多的著墨。")]),e._v(" "),t("h3",{attrs:{id:"level-1-以太坊虛擬機-ethereum-virtual-machine"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#level-1-以太坊虛擬機-ethereum-virtual-machine"}},[e._v("#")]),e._v(" Level 1: 以太坊虛擬機 Ethereum Virtual Machine")]),e._v(" "),t("p",[e._v("除了共識層之外,以太坊與比特幣最大的差異在於以太坊有著良好的智能合約執行環境。")]),e._v(" "),t("p",[e._v("以太坊虛擬機是執行一切交易的核心,從轉帳、部署合約、與合約互動等,無處不是它的範疇。它就像是你最忠實的手機默默地幫你執行所需要的 App。")]),e._v(" "),t("p",[e._v("作為使用者當然是不需要知道以太坊虛擬機是怎麼執行的,甚至不需要知道有以太坊虛擬機的角色存在。然而,與參考文內的說法不同,我認為至少智能合約的開發者需要深入理解以太坊虛擬機的指令,理解越深,越能寫出更省燃料,更精巧的合約。")]),e._v(" "),t("h3",{attrs:{id:"level-2-智能合約-smart-contract"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#level-2-智能合約-smart-contract"}},[e._v("#")]),e._v(" Level 2: 智能合約 Smart Contract")]),e._v(" "),t("p",[e._v("到這裡就是大家常說的 Web 3.0 的開發者了,開發者們會通過撰寫智能合約的程式語言,將商業邏輯部署在以太坊上。")]),e._v(" "),t("p",[e._v("即使到了智能合約的層級,使用者依然不需要對此層級有什麼了解,因為很多合約不一定是開放原始碼的,既然看不見,那只能從開發者提供的公開介面去做互動,相對受限。")]),e._v(" "),t("p",[e._v("而作為 DApp 的開發者,這層級開始就是他們吃飯的根據。他們需要熟悉所有智能合約語言與以太坊的特性,這也是許多應用生態系的所在,比如說穩定幣(Stable Coin)、去中心化交易所(Decentralized Exchange)等都是在這個層級被開發出來的。")]),e._v(" "),t("h3",{attrs:{id:"level-3-以太坊節點-ethereum-nodes"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#level-3-以太坊節點-ethereum-nodes"}},[e._v("#")]),e._v(" Level 3: 以太坊節點 Ethereum Nodes")]),e._v(" "),t("p",[e._v("這裡就是使用者們能與以太坊網路上的應用互動的最低層級,通過節點,我們可以存取在區塊鏈上的資料、發送交易到網路上。")]),e._v(" "),t("p",[e._v("除此之外,也是驗證者參與的層級,他們通過執行節點與驗證者軟體,驗證區塊上每筆交易的正確性,來確保了整個網路的安全與資料的精準度。他們也承載著整個區塊鏈網路的資料(是的,所有的網路狀態都會存在節點中)。")]),e._v(" "),t("p",[e._v("而節點也提供了最低層級的 JSON-RPC API ,讓應用程式可以與節點互動,這些 API 包含但不限於:")]),e._v(" "),t("ol",[t("li",[e._v("讀取區塊鏈上的資料,如:使用者帳戶的餘額")]),e._v(" "),t("li",[e._v("發送交易到網路上,如:轉帳、部署合約、與合約互動")])]),e._v(" "),t("h3",{attrs:{id:"level-4-以太坊客戶端-apis-ethereum-client-apis"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#level-4-以太坊客戶端-apis-ethereum-client-apis"}},[e._v("#")]),e._v(" Level 4: 以太坊客戶端 APIs Ethereum Client APIs")]),e._v(" "),t("p",[e._v("直接與以太坊節點互動雖然暴力但簡單有效,但每次都要手動操作底層 JSON-RPC 的 API 實在不甚方便。")]),e._v(" "),t("p",[e._v("為了方便開發者與使用者與節點互動,在節點之上包裝了一層客戶端,將各種方便的函式庫封裝好,以達到更簡潔與便利的操作。")]),e._v(" "),t("p",[e._v("以網頁軟體為例,使用 JavaScript API ,如 ether.js 的函式庫來與客戶端互動。若是在伺服器端上的軟體,也能使用 Python 或 Java API 來互動。")]),e._v(" "),t("p",[e._v("這些 API 建構了很多好用的輪子,讓開發者與使用者能從走路變成騎車,節省很多重複的操作,比如 ETH、Gwei、Wei 間的單位轉換等這類常用但 JSON-RPC API 不提供的功能;又比如把合約的介面做了簡單的封裝,能更直覺地操作合約內的函式與資料。")]),e._v(" "),t("h3",{attrs:{id:"level-5-終端使用者的應用層-end-user-applications"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#level-5-終端使用者的應用層-end-user-applications"}},[e._v("#")]),e._v(" Level 5: 終端使用者的應用層 End-User Applications")]),e._v(" "),t("p",[e._v("在這裡便是大眾使用者參與的層級,他們不需要知道以太坊虛擬機、不用理解智能合約、不需要關注以太坊節點、也不用操作以太坊客戶端 API、甚至不需要知道這個網站或者軟體的背後是不是使用區塊鏈技術。")]),e._v(" "),t("p",[e._v("當這件事發生的時候,我認為才是區塊鏈真的走進大眾的眼裡,如同在銀行匯款轉帳時,我們不曾去思考過銀行怎麼儲存貨幣;在買賣股票時,不需要知道內部的撮合演算法與股票紀錄的方式。一切就是對介面的操作,就這麼簡單。")]),e._v(" "),t("p",[e._v("在這層級解決了特定的痛點與問題,但不需要讓使用者知道這背後是區塊鏈。而這,也是我對區塊鏈應用的未來想像,也是現在從業人員的終極目標。")])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/33.4a908e19.js b/.vuepress/dist/assets/js/33.cc69c412.js similarity index 99% rename from .vuepress/dist/assets/js/33.4a908e19.js rename to .vuepress/dist/assets/js/33.cc69c412.js index 5dac83c..b9bf018 100644 --- a/.vuepress/dist/assets/js/33.4a908e19.js +++ b/.vuepress/dist/assets/js/33.cc69c412.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[33],{358:function(e,r,t){"use strict";t.r(r);var a=t(17),n=Object(a.a)({},(function(){var e=this,r=e._self._c;return r("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[r("h1",{attrs:{id:"以太坊改良提案-ethereum-improvement-proposals-eip"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#以太坊改良提案-ethereum-improvement-proposals-eip"}},[e._v("#")]),e._v(" 以太坊改良提案 Ethereum Improvement Proposals (EIP)")]),e._v(" "),r("p",[e._v("由於「在 2022 年我們該如何寫智能合約」影片系列即將進入與 ERC20 代幣等相關的主題,因此我們接下來幾天會依序來聊聊什麼是 EIP 與 ERC,以及目前主流的幾個 ERC 的標準。")]),e._v(" "),r("h2",{attrs:{id:"什麼是以太坊改良提案"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#什麼是以太坊改良提案"}},[e._v("#")]),e._v(" 什麼是以太坊改良提案")]),e._v(" "),r("p",[e._v("以太坊改良提案的標準被定義在 "),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-1",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP 提案編號 1"),r("OutboundLink")],1),e._v("。本文將以 EIP-1 為主,進行修改與翻譯所寫成。")]),e._v(" "),r("p",[e._v("以太坊改良提案 Ethereum Improvement Proposals,簡稱 EIPs ,它是一份設計文件用來描述提案內容、定義以太坊的新功能或新特性、或定義新流程。\n在這份文件中,應該提供清晰簡潔的功能技術規格、需要這個改良的理由。且提案者須負責跟社群進行溝通,並記錄下各種不同的意見與建議。在取得共識之後,才會正式被承認。")]),e._v(" "),r("h2",{attrs:{id:"以太坊改良提案的種類"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#以太坊改良提案的種類"}},[e._v("#")]),e._v(" 以太坊改良提案的種類")]),e._v(" "),r("p",[e._v("一般來說,EIP 可分為三大類:")]),e._v(" "),r("ol",[r("li",[r("p",[e._v("Standards Track EIP:\n任何大幅對以太坊實作相關的改變都應屬於此種類,包含但不限於:對網路協議的修改、對區塊或交易的驗證機制的修改、對應用標準的修訂等等。\nStandards Track EIP 須包含以下幾個部分:\nA. 設計文件(design document)\nB. 實作(implementation)\nC. 對正式規格的更新(updated formal specification)\n且他通常會再被細分成以下四個子種類:\n1.1. 核心(Core):這類的修改可能需要仰賴共識分叉,如 "),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-5",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-5: Gas Usage for "),r("code",[e._v("RETURN")]),e._v(" and "),r("code",[e._v("CALL*")]),r("OutboundLink")],1),e._v(", "),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-101",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-101: Serenity Currency and Crypto Abstraction"),r("OutboundLink")],1),e._v(";或者不一定需要共識分叉但對核心開發(Core Dev)息息相關,如:"),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-86",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-86: Abstraction of transaction origin and signature"),r("OutboundLink")],1),e._v("\n1.2. 網路(Networking):這類的修改著重在 "),r("code",[e._v("devp2p")]),e._v(",如 "),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-8",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-8: devp2p Forward Compatibility Requirements for Homestead"),r("OutboundLink")],1),e._v(" ;輕量以太坊子協議(Light Ethereum Subprotocol);或針對 "),r("code",[e._v("whisper")]),e._v(" 與 "),r("code",[e._v("swarm")]),e._v(" 的網路協議規格的改進。\n1.3. 介面(Interface):包含對客戶端的 API 或 RPC 的規格與標準的改進;對語言層級標準的改進,像是 EVM 指令的改進,如:"),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-6",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-6: Renaming SUICIDE opcode"),r("OutboundLink")],1),e._v(";與合約的 ABIs 定義。\n1.4. ERC:應用層級的標準與公約,包含合約的標準,如:"),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-20",target:"_blank",rel:"noopener noreferrer"}},[e._v("代幣標準 EIP-20"),r("OutboundLink")],1),e._v(","),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-137",target:"_blank",rel:"noopener noreferrer"}},[e._v("以太坊域名系統 EIP-137"),r("OutboundLink")],1),e._v(",函式庫或套件的格式,與錢包的格式等。")])]),e._v(" "),r("li",[r("p",[e._v("Meta EIP (或 Process EIP)")])])]),e._v(" "),r("p",[e._v("流程型 EIP ,描述了對以太坊的流程,或對現存流程的修正。流程型 EIP 定義了除在 Standards Track EIPs 裡面所提的以太坊協議本體外的其他領域。如:提出一個無關以太坊程式碼庫(Ethereum's codebase)的實作。這類型的 EIP 通常需要得到社群的共識,因此開發者與使用者都必須重視以待。例如:程序、指南、對決定流程的改變、對開發工具或開發環境的修改等。")]),e._v(" "),r("ol",{attrs:{start:"3"}},[r("li",[e._v("資訊型 EIP(Informational EIP)")])]),e._v(" "),r("p",[e._v("資訊型的 EIP 描述了對以太坊的設計主題、提供給以太坊社群通用的指南或資訊,但不包含提出新的特性或功能。\n且資訊型 EIP 不需要取得以太坊社群的共識或者推薦,因此使用者與開發者不需要特別在意資訊型 EIP,也不一定要遵守裡頭的建議。")]),e._v(" "),r("h2",{attrs:{id:"eip-的核心概念"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#eip-的核心概念"}},[e._v("#")]),e._v(" EIP 的核心概念")]),e._v(" "),r("p",[e._v("一個 EIP 應著重在擔一個關鍵提案或者想法,越專注在單點,則越容易讓 EIP 被接受。反之,一個包山包海且過分複雜的 EIP 很難被社群接受。\n此外,有共通性的修改才需要發起 EIP,若只針對特定的客戶端的修改,那不需要 EIP,只需要去該客戶端那發問即可;反之,當這個修改需要仰賴多個客戶端、或定義會影響到眾多應用的新標準就需要發起 EIP。")]),e._v(" "),r("h2",{attrs:{id:"eip-的限制"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#eip-的限制"}},[e._v("#")]),e._v(" EIP 的限制")]),e._v(" "),r("p",[e._v("每一個 EIP 都需達到最低的標準。它必須有一份清晰且對於提案的改良有著完善描述。且提出的實作必須是穩固且不會過份複雜化協議。")]),e._v(" "),r("h2",{attrs:{id:"關於核心-eips-的特殊要求"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#關於核心-eips-的特殊要求"}},[e._v("#")]),e._v(" 關於核心 EIPs 的特殊要求")]),e._v(" "),r("p",[e._v("若 Core EIP 需要修改以太坊虛擬機,在文件中應參照到該指令或以以下格式定義指令:")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("REVERT (0xfe)\n")])])])])}),[],!1,null,null,null);r.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[33],{353:function(e,r,t){"use strict";t.r(r);var a=t(17),n=Object(a.a)({},(function(){var e=this,r=e._self._c;return r("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[r("h1",{attrs:{id:"以太坊改良提案-ethereum-improvement-proposals-eip"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#以太坊改良提案-ethereum-improvement-proposals-eip"}},[e._v("#")]),e._v(" 以太坊改良提案 Ethereum Improvement Proposals (EIP)")]),e._v(" "),r("p",[e._v("由於「在 2022 年我們該如何寫智能合約」影片系列即將進入與 ERC20 代幣等相關的主題,因此我們接下來幾天會依序來聊聊什麼是 EIP 與 ERC,以及目前主流的幾個 ERC 的標準。")]),e._v(" "),r("h2",{attrs:{id:"什麼是以太坊改良提案"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#什麼是以太坊改良提案"}},[e._v("#")]),e._v(" 什麼是以太坊改良提案")]),e._v(" "),r("p",[e._v("以太坊改良提案的標準被定義在 "),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-1",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP 提案編號 1"),r("OutboundLink")],1),e._v("。本文將以 EIP-1 為主,進行修改與翻譯所寫成。")]),e._v(" "),r("p",[e._v("以太坊改良提案 Ethereum Improvement Proposals,簡稱 EIPs ,它是一份設計文件用來描述提案內容、定義以太坊的新功能或新特性、或定義新流程。\n在這份文件中,應該提供清晰簡潔的功能技術規格、需要這個改良的理由。且提案者須負責跟社群進行溝通,並記錄下各種不同的意見與建議。在取得共識之後,才會正式被承認。")]),e._v(" "),r("h2",{attrs:{id:"以太坊改良提案的種類"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#以太坊改良提案的種類"}},[e._v("#")]),e._v(" 以太坊改良提案的種類")]),e._v(" "),r("p",[e._v("一般來說,EIP 可分為三大類:")]),e._v(" "),r("ol",[r("li",[r("p",[e._v("Standards Track EIP:\n任何大幅對以太坊實作相關的改變都應屬於此種類,包含但不限於:對網路協議的修改、對區塊或交易的驗證機制的修改、對應用標準的修訂等等。\nStandards Track EIP 須包含以下幾個部分:\nA. 設計文件(design document)\nB. 實作(implementation)\nC. 對正式規格的更新(updated formal specification)\n且他通常會再被細分成以下四個子種類:\n1.1. 核心(Core):這類的修改可能需要仰賴共識分叉,如 "),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-5",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-5: Gas Usage for "),r("code",[e._v("RETURN")]),e._v(" and "),r("code",[e._v("CALL*")]),r("OutboundLink")],1),e._v(", "),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-101",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-101: Serenity Currency and Crypto Abstraction"),r("OutboundLink")],1),e._v(";或者不一定需要共識分叉但對核心開發(Core Dev)息息相關,如:"),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-86",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-86: Abstraction of transaction origin and signature"),r("OutboundLink")],1),e._v("\n1.2. 網路(Networking):這類的修改著重在 "),r("code",[e._v("devp2p")]),e._v(",如 "),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-8",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-8: devp2p Forward Compatibility Requirements for Homestead"),r("OutboundLink")],1),e._v(" ;輕量以太坊子協議(Light Ethereum Subprotocol);或針對 "),r("code",[e._v("whisper")]),e._v(" 與 "),r("code",[e._v("swarm")]),e._v(" 的網路協議規格的改進。\n1.3. 介面(Interface):包含對客戶端的 API 或 RPC 的規格與標準的改進;對語言層級標準的改進,像是 EVM 指令的改進,如:"),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-6",target:"_blank",rel:"noopener noreferrer"}},[e._v("EIP-6: Renaming SUICIDE opcode"),r("OutboundLink")],1),e._v(";與合約的 ABIs 定義。\n1.4. ERC:應用層級的標準與公約,包含合約的標準,如:"),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-20",target:"_blank",rel:"noopener noreferrer"}},[e._v("代幣標準 EIP-20"),r("OutboundLink")],1),e._v(","),r("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-137",target:"_blank",rel:"noopener noreferrer"}},[e._v("以太坊域名系統 EIP-137"),r("OutboundLink")],1),e._v(",函式庫或套件的格式,與錢包的格式等。")])]),e._v(" "),r("li",[r("p",[e._v("Meta EIP (或 Process EIP)")])])]),e._v(" "),r("p",[e._v("流程型 EIP ,描述了對以太坊的流程,或對現存流程的修正。流程型 EIP 定義了除在 Standards Track EIPs 裡面所提的以太坊協議本體外的其他領域。如:提出一個無關以太坊程式碼庫(Ethereum's codebase)的實作。這類型的 EIP 通常需要得到社群的共識,因此開發者與使用者都必須重視以待。例如:程序、指南、對決定流程的改變、對開發工具或開發環境的修改等。")]),e._v(" "),r("ol",{attrs:{start:"3"}},[r("li",[e._v("資訊型 EIP(Informational EIP)")])]),e._v(" "),r("p",[e._v("資訊型的 EIP 描述了對以太坊的設計主題、提供給以太坊社群通用的指南或資訊,但不包含提出新的特性或功能。\n且資訊型 EIP 不需要取得以太坊社群的共識或者推薦,因此使用者與開發者不需要特別在意資訊型 EIP,也不一定要遵守裡頭的建議。")]),e._v(" "),r("h2",{attrs:{id:"eip-的核心概念"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#eip-的核心概念"}},[e._v("#")]),e._v(" EIP 的核心概念")]),e._v(" "),r("p",[e._v("一個 EIP 應著重在擔一個關鍵提案或者想法,越專注在單點,則越容易讓 EIP 被接受。反之,一個包山包海且過分複雜的 EIP 很難被社群接受。\n此外,有共通性的修改才需要發起 EIP,若只針對特定的客戶端的修改,那不需要 EIP,只需要去該客戶端那發問即可;反之,當這個修改需要仰賴多個客戶端、或定義會影響到眾多應用的新標準就需要發起 EIP。")]),e._v(" "),r("h2",{attrs:{id:"eip-的限制"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#eip-的限制"}},[e._v("#")]),e._v(" EIP 的限制")]),e._v(" "),r("p",[e._v("每一個 EIP 都需達到最低的標準。它必須有一份清晰且對於提案的改良有著完善描述。且提出的實作必須是穩固且不會過份複雜化協議。")]),e._v(" "),r("h2",{attrs:{id:"關於核心-eips-的特殊要求"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#關於核心-eips-的特殊要求"}},[e._v("#")]),e._v(" 關於核心 EIPs 的特殊要求")]),e._v(" "),r("p",[e._v("若 Core EIP 需要修改以太坊虛擬機,在文件中應參照到該指令或以以下格式定義指令:")]),e._v(" "),r("div",{staticClass:"language- extra-class"},[r("pre",{pre:!0,attrs:{class:"language-text"}},[r("code",[e._v("REVERT (0xfe)\n")])])])])}),[],!1,null,null,null);r.default=n.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/35.e73f9098.js b/.vuepress/dist/assets/js/35.770ffdf6.js similarity index 99% rename from .vuepress/dist/assets/js/35.e73f9098.js rename to .vuepress/dist/assets/js/35.770ffdf6.js index 5ce5040..ad5779e 100644 --- a/.vuepress/dist/assets/js/35.e73f9098.js +++ b/.vuepress/dist/assets/js/35.770ffdf6.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[35],{359: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/.vuepress/dist/assets/js/36.dc5f1bb9.js b/.vuepress/dist/assets/js/36.f857026a.js similarity index 97% rename from .vuepress/dist/assets/js/36.dc5f1bb9.js rename to .vuepress/dist/assets/js/36.f857026a.js index 07e3969..ada72c5 100644 --- a/.vuepress/dist/assets/js/36.dc5f1bb9.js +++ b/.vuepress/dist/assets/js/36.f857026a.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[36],{354: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/.vuepress/dist/assets/js/37.4f5e73b1.js b/.vuepress/dist/assets/js/37.ed93802d.js similarity index 98% rename from .vuepress/dist/assets/js/37.4f5e73b1.js rename to .vuepress/dist/assets/js/37.ed93802d.js index 00d213b..91f6c2e 100644 --- a/.vuepress/dist/assets/js/37.4f5e73b1.js +++ b/.vuepress/dist/assets/js/37.ed93802d.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[37],{356: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/.vuepress/dist/assets/js/38.35ee4ee4.js b/.vuepress/dist/assets/js/38.7d25c164.js similarity index 99% rename from .vuepress/dist/assets/js/38.35ee4ee4.js rename to .vuepress/dist/assets/js/38.7d25c164.js index 484974d..efe39ce 100644 --- a/.vuepress/dist/assets/js/38.35ee4ee4.js +++ b/.vuepress/dist/assets/js/38.7d25c164.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[38],{362: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],{361: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/.vuepress/dist/assets/js/39.1a15401d.js b/.vuepress/dist/assets/js/39.27a34c86.js similarity index 97% rename from .vuepress/dist/assets/js/39.1a15401d.js rename to .vuepress/dist/assets/js/39.27a34c86.js index 0eb4160..6c61ba9 100644 --- a/.vuepress/dist/assets/js/39.1a15401d.js +++ b/.vuepress/dist/assets/js/39.27a34c86.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[39],{357:function(n,e,t){"use strict";t.r(e);var a=t(17),r=Object(a.a)({},(function(){var n=this,e=n._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":n.$parent.slotKey}},[e("h1",{attrs:{id:"erc721-的列舉擴充-enumeration-extension"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#erc721-的列舉擴充-enumeration-extension"}},[n._v("#")]),n._v(" ERC721 的列舉擴充(enumeration extension)")]),n._v(" "),e("p",[n._v("除了元資料擴充功能以外,為了能方便查詢發行量、能依序列出所有未被銷毀的 NFT、以及能列舉特定帳戶持有的 NFT,因此設計出這個介面。")]),n._v(" "),e("h2",{attrs:{id:"列舉擴充介面"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#列舉擴充介面"}},[n._v("#")]),n._v(" 列舉擴充介面")]),n._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[n._v("interface ERC721Enumerable /* is ERC721 */ {\n /// 回傳目前發行的 ERC721 總量\n function totalSupply() external view returns (uint256);\n\n /// 回傳第 `_index` 個未被銷毀的 NFT tokenId\n function tokenByIndex(uint256 _index) external view returns (uint256);\n\n /// 回傳第 `_index` 個由 `_owner` 帳戶持有的 NFT tokenId\n function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);\n}\n")])])]),e("h2",{attrs:{id:"代價"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#代價"}},[n._v("#")]),n._v(" 代價")]),n._v(" "),e("p",[n._v("當然,凡事都有代價,尤其是要方便查詢的話,自然需要在區塊鏈上多儲存資訊。以 "),e("a",{attrs:{href:"https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/extensions/ERC721Enumerable.sol",target:"_blank",rel:"noopener noreferrer"}},[n._v("OpenZeppelin 的 ERC721 Enumerable 合約為例"),e("OutboundLink")],1),n._v(",我們可以發現它新增了以下幾個狀態變數:")]),n._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[n._v(" // 映射擁有者到他所持有的 NFT 列表\n // 擁有者位址 => Index => TokenId\n mapping(address => mapping(uint256 => uint256)) private _ownedTokens;\n\n // 映射 token ID 到擁有者的 NFT 列表中的 Index \n // TokenId => Index of `_ownedTokens`\n mapping(uint256 => uint256) private _ownedTokensIndex;\n\n // 用來儲存所有 token ID,因此可以快速查詢總發行量,也能方便列舉\n uint256[] private _allTokens;\n\n // 映射 token ID 到所有 token ID 陣列的 Index\n // token ID => Index of `_allTokens`\n mapping(uint256 => uint256) private _allTokensIndex;\n")])])]),e("p",[n._v("由於提供此功能所付出的代價不低,因此也有其他的 ERC721 的變種,就讓我們後面再來聊聊吧。")])])}),[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[39],{359:function(n,e,t){"use strict";t.r(e);var a=t(17),r=Object(a.a)({},(function(){var n=this,e=n._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":n.$parent.slotKey}},[e("h1",{attrs:{id:"erc721-的列舉擴充-enumeration-extension"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#erc721-的列舉擴充-enumeration-extension"}},[n._v("#")]),n._v(" ERC721 的列舉擴充(enumeration extension)")]),n._v(" "),e("p",[n._v("除了元資料擴充功能以外,為了能方便查詢發行量、能依序列出所有未被銷毀的 NFT、以及能列舉特定帳戶持有的 NFT,因此設計出這個介面。")]),n._v(" "),e("h2",{attrs:{id:"列舉擴充介面"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#列舉擴充介面"}},[n._v("#")]),n._v(" 列舉擴充介面")]),n._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[n._v("interface ERC721Enumerable /* is ERC721 */ {\n /// 回傳目前發行的 ERC721 總量\n function totalSupply() external view returns (uint256);\n\n /// 回傳第 `_index` 個未被銷毀的 NFT tokenId\n function tokenByIndex(uint256 _index) external view returns (uint256);\n\n /// 回傳第 `_index` 個由 `_owner` 帳戶持有的 NFT tokenId\n function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);\n}\n")])])]),e("h2",{attrs:{id:"代價"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#代價"}},[n._v("#")]),n._v(" 代價")]),n._v(" "),e("p",[n._v("當然,凡事都有代價,尤其是要方便查詢的話,自然需要在區塊鏈上多儲存資訊。以 "),e("a",{attrs:{href:"https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/extensions/ERC721Enumerable.sol",target:"_blank",rel:"noopener noreferrer"}},[n._v("OpenZeppelin 的 ERC721 Enumerable 合約為例"),e("OutboundLink")],1),n._v(",我們可以發現它新增了以下幾個狀態變數:")]),n._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[n._v(" // 映射擁有者到他所持有的 NFT 列表\n // 擁有者位址 => Index => TokenId\n mapping(address => mapping(uint256 => uint256)) private _ownedTokens;\n\n // 映射 token ID 到擁有者的 NFT 列表中的 Index \n // TokenId => Index of `_ownedTokens`\n mapping(uint256 => uint256) private _ownedTokensIndex;\n\n // 用來儲存所有 token ID,因此可以快速查詢總發行量,也能方便列舉\n uint256[] private _allTokens;\n\n // 映射 token ID 到所有 token ID 陣列的 Index\n // token ID => Index of `_allTokens`\n mapping(uint256 => uint256) private _allTokensIndex;\n")])])]),e("p",[n._v("由於提供此功能所付出的代價不低,因此也有其他的 ERC721 的變種,就讓我們後面再來聊聊吧。")])])}),[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/41.dca031ce.js b/.vuepress/dist/assets/js/41.0145fe58.js similarity index 97% rename from .vuepress/dist/assets/js/41.dca031ce.js rename to .vuepress/dist/assets/js/41.0145fe58.js index 70926b4..2ec5ac6 100644 --- a/.vuepress/dist/assets/js/41.dca031ce.js +++ b/.vuepress/dist/assets/js/41.0145fe58.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[41],{361:function(t,r,a){"use strict";a.r(r);var _=a(17),v=Object(_.a)({},(function(){var t=this,r=t._self._c;return r("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[r("h1",{attrs:{id:"erc721r-有鑑賞期的-nft"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#erc721r-有鑑賞期的-nft"}},[t._v("#")]),t._v(" ERC721R - 有鑑賞期的 NFT")]),t._v(" "),r("p",[r("a",{attrs:{href:"https://github.com/exo-digital-labs/ERC721R",target:"_blank",rel:"noopener noreferrer"}},[t._v("ERC721R Repo"),r("OutboundLink")],1)]),t._v(" "),r("p",[t._v("如果大家之前有關注到 NFT 相關的新聞,相信一堆專門賣 JPG 圖片的割韭菜專案滿街跑,隨著這些惡劣的團隊毀滅著 NFT 的名聲,越來越多的人不再信任認真做事的團隊,而這便是 ERC721R 想解決的問題。")]),t._v(" "),r("h2",{attrs:{id:"設計理念"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#設計理念"}},[t._v("#")]),t._v(" 設計理念")]),t._v(" "),r("p",[t._v("由於不少的 NFT 專案在發售之際馬上會被有心人士(或者惡劣的團隊本身)捲款潛逃,進而導致 NFT 的價值歸零,讓收藏家血本無歸。而 ERC721R 的標準便新增了鎖倉期間,在鑑賞期內,團隊無法提領合約中的 ETH,必須等鎖倉期過後才能提領。而這段期間只要買家覺得毛毛的,想退款,只需支付交易手續費便能獲得退款。")]),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("ol",[r("li",[t._v("降低購買風險,最慘也能拿回部分的錢(扣掉手續費)")]),t._v(" "),r("li",[t._v("不怕專案團隊落跑")])]),t._v(" "),r("p",[t._v("對賣家而言:")]),t._v(" "),r("ol",[r("li",[t._v("可增加買家意願")]),t._v(" "),r("li",[t._v("也增加買家的信任,誰叫一堆團隊專門在詐騙呢")])]),t._v(" "),r("p",[t._v("對雙方而言:")]),t._v(" "),r("ol",[r("li",[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("如果鎖倉期間過長,好比說發售後 1000 天內都是鑑賞期,代表在這段期間開發者完全不能從裡面提領任何的 ETH,然後呢?然後開發者就餓死了╮(╯▽╰)╭")]),t._v(" "),r("p",[t._v("在該標準的文件中有提到目前的幾個案例:\nExodia 提供 14 天鑑賞期\nCurious Addy’s Trading Club 提供 100 天鑑賞期\nCryptoFighters 提供 45 天鑑賞期")]),t._v(" "),r("p",[t._v("請以團隊不會餓死,又相對合理的時間為主,這樣才能真的對雙方都有好處。")])])}),[],!1,null,null,null);r.default=v.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[41],{362:function(t,r,a){"use strict";a.r(r);var _=a(17),v=Object(_.a)({},(function(){var t=this,r=t._self._c;return r("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[r("h1",{attrs:{id:"erc721r-有鑑賞期的-nft"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#erc721r-有鑑賞期的-nft"}},[t._v("#")]),t._v(" ERC721R - 有鑑賞期的 NFT")]),t._v(" "),r("p",[r("a",{attrs:{href:"https://github.com/exo-digital-labs/ERC721R",target:"_blank",rel:"noopener noreferrer"}},[t._v("ERC721R Repo"),r("OutboundLink")],1)]),t._v(" "),r("p",[t._v("如果大家之前有關注到 NFT 相關的新聞,相信一堆專門賣 JPG 圖片的割韭菜專案滿街跑,隨著這些惡劣的團隊毀滅著 NFT 的名聲,越來越多的人不再信任認真做事的團隊,而這便是 ERC721R 想解決的問題。")]),t._v(" "),r("h2",{attrs:{id:"設計理念"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#設計理念"}},[t._v("#")]),t._v(" 設計理念")]),t._v(" "),r("p",[t._v("由於不少的 NFT 專案在發售之際馬上會被有心人士(或者惡劣的團隊本身)捲款潛逃,進而導致 NFT 的價值歸零,讓收藏家血本無歸。而 ERC721R 的標準便新增了鎖倉期間,在鑑賞期內,團隊無法提領合約中的 ETH,必須等鎖倉期過後才能提領。而這段期間只要買家覺得毛毛的,想退款,只需支付交易手續費便能獲得退款。")]),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("ol",[r("li",[t._v("降低購買風險,最慘也能拿回部分的錢(扣掉手續費)")]),t._v(" "),r("li",[t._v("不怕專案團隊落跑")])]),t._v(" "),r("p",[t._v("對賣家而言:")]),t._v(" "),r("ol",[r("li",[t._v("可增加買家意願")]),t._v(" "),r("li",[t._v("也增加買家的信任,誰叫一堆團隊專門在詐騙呢")])]),t._v(" "),r("p",[t._v("對雙方而言:")]),t._v(" "),r("ol",[r("li",[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("如果鎖倉期間過長,好比說發售後 1000 天內都是鑑賞期,代表在這段期間開發者完全不能從裡面提領任何的 ETH,然後呢?然後開發者就餓死了╮(╯▽╰)╭")]),t._v(" "),r("p",[t._v("在該標準的文件中有提到目前的幾個案例:\nExodia 提供 14 天鑑賞期\nCurious Addy’s Trading Club 提供 100 天鑑賞期\nCryptoFighters 提供 45 天鑑賞期")]),t._v(" "),r("p",[t._v("請以團隊不會餓死,又相對合理的時間為主,這樣才能真的對雙方都有好處。")])])}),[],!1,null,null,null);r.default=v.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/42.4dcfb5f8.js b/.vuepress/dist/assets/js/42.55c3ac28.js similarity index 99% rename from .vuepress/dist/assets/js/42.4dcfb5f8.js rename to .vuepress/dist/assets/js/42.55c3ac28.js index b86e253..42587ea 100644 --- a/.vuepress/dist/assets/js/42.4dcfb5f8.js +++ b/.vuepress/dist/assets/js/42.55c3ac28.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[42],{363:function(e,n,r){"use strict";r.r(n);var a=r(17),t=Object(a.a)({},(function(){var e=this,n=e._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[n("h1",{attrs:{id:"erc1155-多元代幣標準-erc20-erc721-我全都要"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#erc1155-多元代幣標準-erc20-erc721-我全都要"}},[e._v("#")]),e._v(" ERC1155 多元代幣標準 - ERC20 + ERC721 我全都要")]),e._v(" "),n("p",[n("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-1155",target:"_blank",rel:"noopener noreferrer"}},[e._v("ERC-1155 MULTI-TOKEN STANDARD"),n("OutboundLink")],1),e._v(" 定義了一個揉合 ERC20 與 ERC721 的新標準,他可以發行同值性代幣(如:ERC20)也能發行非同值性代幣(如:NFT ERC721)。")]),e._v(" "),n("h2",{attrs:{id:"介面"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#介面"}},[e._v("#")]),e._v(" 介面")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('interface ERC1155 /* is ERC165 */ {\n /// 當代幣被轉移時,`TransferSingle` 必須被觸發,即使是轉移 `0` 個代幣也是,轉移的行為包含「鑄造」與「銷毀」。\n /// `_operator` 是發起交易的位址,即 `msg.sender`\n /// `_from` 是持有者的位址;當「鑄造」新代幣時,此參數為位址 `0x0`\n /// `_to` 是接收者的位址;當「銷毀」代幣時,此參數為位址 `0x0`\n /// `_id` 為被轉移的 token ID\n /// `_value` 為被轉移的 token 數量\n event TransferSingle(address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value);\n\n /// 當代幣被轉移時,`TransferBatch` 必須被觸發,即使是轉移 `0` 個代幣也是,轉移的行為包含「鑄造」與「銷毀」。\n /// `_operator` 是發起交易的位址,即 `msg.sender`\n /// `_from` 是持有者的位址;當「鑄造」新代幣時,此參數為位址 `0x0`\n /// `_to` 是接收者的位址;當「銷毀」代幣時,此參數為位址 `0x0`\n /// `_ids` 為被轉移的 token ID 列表\n /// `_values` 為被轉移的 token 數量列表,其順序與長度需與 `_ids` 一致。\n event TransferBatch(address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values);\n\n /// 授權事件,當持有者「授權」或「撤銷」第三方位址管理全部代幣的權力時被觸發。\n /// `_owner` 為持有者位址\n /// `_operator` 為被授權者位址\n /// `_approved` 為授權(`true`)或撤銷(`false`)\n event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);\n\n /// URI 更新事件\n /// 當代幣的 URI 被更新時,必須觸發此事件\n /// `_value` 代表更新後的 URI\n /// `_id` 代表被更新的 token ID\n event URI(string _value, uint256 indexed _id);\n\n /// 呼叫者(`msg.sender`)從持有者(`_from`)轉移 `_value` 數量的特定代幣(`_id`)給接收者(`_to`)\n /// 呼叫者應先獲得持有者的授權,或呼叫者就是持有者本人\n /// 特殊情況:\n /// 1. 當接收者(`_to`)為位址 `0x0` 時,回朔(revert)交易\n /// 2. 當持有者(`_from`)所持有的代幣(`_id`)餘額低於要轉移的數量(`_value`)時,回朔交易\n /// 3. 當發生任何錯誤時,回朔交易\n /// 當此函式被呼叫時,必須觸發 `TransferSingle` 事件\n function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external;\n\n Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc).\n After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). \n @param _from Source address\n @param _to Target address\n @param _ids IDs of each token type (order and length must match _values array)\n @param _values Transfer amounts per token type (order and length must match _ids array)\n @param _data Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to`\n */\n /// 呼叫者(`msg.sender`)從持有者(`_from`)轉移 `_values` 數量的多種特定代幣(`_ids`)給接收者(`_to`)\n /// 呼叫者應先獲得持有者的授權,或呼叫者就是持有者本人\n /// 特殊情況:\n /// 1. 當接收者(`_to`)為位址 `0x0` 時,回朔(revert)交易\n /// 2. 當持有者(`_from`)所持有的任何一種代幣(`_ids`)餘額低於要轉移的對應數量(`_values`)時,回朔交易\n ///. 3. 當轉移數量列表的長度與轉移代幣列表的長度不相符時,回朔交易\n /// 3. 當發生任何錯誤時,回朔交易\n /// 當此函式被呼叫時,必須觸發 `TransferBatch` 或 `TransferSingle` 事件,需特別注意,在事件中的轉移代幣與數量的順序應嚴格與呼叫此函式的代幣與數量順序一致。\n function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external;\n\n /// 查詢持有者帳戶中特定 token ID 的餘額\n /// `_owner` 為持有者帳號\n /// `_id` 為想查詢的 token id\n /// 回傳該代幣的餘額\n function balanceOf(address _owner, uint256 _id) external view returns (uint256);\n\n /// 「帳戶」對「Token ID」的餘額列表\n /// `_owners` 為持有者列表\n /// `_ids` 為想查詢的 token id 列表\n /// 回傳一個列表,每個餘額為對應順序的(持有者,Token ID)的餘額\n function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory);\n\n /// 呼叫者(`msg.sender`)授權給特定第三方位址管理所有代幣的權力\n /// `_operator` 為第三方位址\n /// `_approved` 為授權(`true`)或撤銷(`false`)\n function setApprovalForAll(address _operator, bool _approved) external;\n\n /// 查詢持有者是否授權給特定第三方位址\n /// `_owner` 為持有者位址\n /// `_operator` 為第三方位址\n /// 回傳 true -> 有授權; false -> 沒有授權\n function isApprovedForAll(address _owner, address _operator) external view returns (bool);\n}\n')])])]),n("h2",{attrs:{id:"為什麼是我全都要"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#為什麼是我全都要"}},[e._v("#")]),e._v(" 為什麼是我全都要")]),e._v(" "),n("p",[e._v("實際上,ERC1155 算是對 ERC721 的改良。ERC721 只允許每個代幣只能有一個獨一無二的編號且數量為一。而 ERC1155 在建立代幣時,每個代幣可以指定發行的數量,因此就能做出擁有相同代幣編號,且數量超過一個情境。")]),e._v(" "),n("p",[e._v("如果想要發行同值性代幣(ERC20),則只需要在 ERC1155 中發行一種編號為 "),n("code",[e._v("0")]),e._v(" 的代幣,數量設定該代幣的總發行量即可。\n反之,若想發行非同值性代幣(ERC721),則在 ERC1155 中發行多種相異編號的代幣,每種類的數量都設定為 "),n("code",[e._v("1")]),e._v(" 即可。")])])}),[],!1,null,null,null);n.default=t.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[42],{364:function(e,n,r){"use strict";r.r(n);var a=r(17),t=Object(a.a)({},(function(){var e=this,n=e._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[n("h1",{attrs:{id:"erc1155-多元代幣標準-erc20-erc721-我全都要"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#erc1155-多元代幣標準-erc20-erc721-我全都要"}},[e._v("#")]),e._v(" ERC1155 多元代幣標準 - ERC20 + ERC721 我全都要")]),e._v(" "),n("p",[n("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-1155",target:"_blank",rel:"noopener noreferrer"}},[e._v("ERC-1155 MULTI-TOKEN STANDARD"),n("OutboundLink")],1),e._v(" 定義了一個揉合 ERC20 與 ERC721 的新標準,他可以發行同值性代幣(如:ERC20)也能發行非同值性代幣(如:NFT ERC721)。")]),e._v(" "),n("h2",{attrs:{id:"介面"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#介面"}},[e._v("#")]),e._v(" 介面")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('interface ERC1155 /* is ERC165 */ {\n /// 當代幣被轉移時,`TransferSingle` 必須被觸發,即使是轉移 `0` 個代幣也是,轉移的行為包含「鑄造」與「銷毀」。\n /// `_operator` 是發起交易的位址,即 `msg.sender`\n /// `_from` 是持有者的位址;當「鑄造」新代幣時,此參數為位址 `0x0`\n /// `_to` 是接收者的位址;當「銷毀」代幣時,此參數為位址 `0x0`\n /// `_id` 為被轉移的 token ID\n /// `_value` 為被轉移的 token 數量\n event TransferSingle(address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value);\n\n /// 當代幣被轉移時,`TransferBatch` 必須被觸發,即使是轉移 `0` 個代幣也是,轉移的行為包含「鑄造」與「銷毀」。\n /// `_operator` 是發起交易的位址,即 `msg.sender`\n /// `_from` 是持有者的位址;當「鑄造」新代幣時,此參數為位址 `0x0`\n /// `_to` 是接收者的位址;當「銷毀」代幣時,此參數為位址 `0x0`\n /// `_ids` 為被轉移的 token ID 列表\n /// `_values` 為被轉移的 token 數量列表,其順序與長度需與 `_ids` 一致。\n event TransferBatch(address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values);\n\n /// 授權事件,當持有者「授權」或「撤銷」第三方位址管理全部代幣的權力時被觸發。\n /// `_owner` 為持有者位址\n /// `_operator` 為被授權者位址\n /// `_approved` 為授權(`true`)或撤銷(`false`)\n event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);\n\n /// URI 更新事件\n /// 當代幣的 URI 被更新時,必須觸發此事件\n /// `_value` 代表更新後的 URI\n /// `_id` 代表被更新的 token ID\n event URI(string _value, uint256 indexed _id);\n\n /// 呼叫者(`msg.sender`)從持有者(`_from`)轉移 `_value` 數量的特定代幣(`_id`)給接收者(`_to`)\n /// 呼叫者應先獲得持有者的授權,或呼叫者就是持有者本人\n /// 特殊情況:\n /// 1. 當接收者(`_to`)為位址 `0x0` 時,回朔(revert)交易\n /// 2. 當持有者(`_from`)所持有的代幣(`_id`)餘額低於要轉移的數量(`_value`)時,回朔交易\n /// 3. 當發生任何錯誤時,回朔交易\n /// 當此函式被呼叫時,必須觸發 `TransferSingle` 事件\n function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external;\n\n Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc).\n After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). \n @param _from Source address\n @param _to Target address\n @param _ids IDs of each token type (order and length must match _values array)\n @param _values Transfer amounts per token type (order and length must match _ids array)\n @param _data Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to`\n */\n /// 呼叫者(`msg.sender`)從持有者(`_from`)轉移 `_values` 數量的多種特定代幣(`_ids`)給接收者(`_to`)\n /// 呼叫者應先獲得持有者的授權,或呼叫者就是持有者本人\n /// 特殊情況:\n /// 1. 當接收者(`_to`)為位址 `0x0` 時,回朔(revert)交易\n /// 2. 當持有者(`_from`)所持有的任何一種代幣(`_ids`)餘額低於要轉移的對應數量(`_values`)時,回朔交易\n ///. 3. 當轉移數量列表的長度與轉移代幣列表的長度不相符時,回朔交易\n /// 3. 當發生任何錯誤時,回朔交易\n /// 當此函式被呼叫時,必須觸發 `TransferBatch` 或 `TransferSingle` 事件,需特別注意,在事件中的轉移代幣與數量的順序應嚴格與呼叫此函式的代幣與數量順序一致。\n function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external;\n\n /// 查詢持有者帳戶中特定 token ID 的餘額\n /// `_owner` 為持有者帳號\n /// `_id` 為想查詢的 token id\n /// 回傳該代幣的餘額\n function balanceOf(address _owner, uint256 _id) external view returns (uint256);\n\n /// 「帳戶」對「Token ID」的餘額列表\n /// `_owners` 為持有者列表\n /// `_ids` 為想查詢的 token id 列表\n /// 回傳一個列表,每個餘額為對應順序的(持有者,Token ID)的餘額\n function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory);\n\n /// 呼叫者(`msg.sender`)授權給特定第三方位址管理所有代幣的權力\n /// `_operator` 為第三方位址\n /// `_approved` 為授權(`true`)或撤銷(`false`)\n function setApprovalForAll(address _operator, bool _approved) external;\n\n /// 查詢持有者是否授權給特定第三方位址\n /// `_owner` 為持有者位址\n /// `_operator` 為第三方位址\n /// 回傳 true -> 有授權; false -> 沒有授權\n function isApprovedForAll(address _owner, address _operator) external view returns (bool);\n}\n')])])]),n("h2",{attrs:{id:"為什麼是我全都要"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#為什麼是我全都要"}},[e._v("#")]),e._v(" 為什麼是我全都要")]),e._v(" "),n("p",[e._v("實際上,ERC1155 算是對 ERC721 的改良。ERC721 只允許每個代幣只能有一個獨一無二的編號且數量為一。而 ERC1155 在建立代幣時,每個代幣可以指定發行的數量,因此就能做出擁有相同代幣編號,且數量超過一個情境。")]),e._v(" "),n("p",[e._v("如果想要發行同值性代幣(ERC20),則只需要在 ERC1155 中發行一種編號為 "),n("code",[e._v("0")]),e._v(" 的代幣,數量設定該代幣的總發行量即可。\n反之,若想發行非同值性代幣(ERC721),則在 ERC1155 中發行多種相異編號的代幣,每種類的數量都設定為 "),n("code",[e._v("1")]),e._v(" 即可。")])])}),[],!1,null,null,null);n.default=t.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/43.3a95c013.js b/.vuepress/dist/assets/js/43.dcf8fa43.js similarity index 98% rename from .vuepress/dist/assets/js/43.3a95c013.js rename to .vuepress/dist/assets/js/43.dcf8fa43.js index f1c3ef5..6195104 100644 --- a/.vuepress/dist/assets/js/43.3a95c013.js +++ b/.vuepress/dist/assets/js/43.dcf8fa43.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[43],{364:function(t,v,_){"use strict";_.r(v);var o=_(17),e=Object(o.a)({},(function(){var t=this,v=t._self._c;return v("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[v("h1",{attrs:{id:"erc1155-的案例"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#erc1155-的案例"}},[t._v("#")]),t._v(" ERC1155 的案例")]),t._v(" "),v("p",[t._v("昨天我們講完了 ERC1155 的標準介面,今天來看看有哪些實際的例子是能套用 ERC1155 的吧!")]),t._v(" "),v("h2",{attrs:{id:"apple-全家桶"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#apple-全家桶"}},[t._v("#")]),t._v(" Apple 全家桶")]),t._v(" "),v("p",[t._v("什麼?你說 iPhone 是 ERC1155?iPad 也是?連 macbook 都是?!\n"),v("img",{attrs:{src:"https://i.imgur.com/dhq3QfA.jpg",alt:""}})]),t._v(" "),v("p",[t._v("當我們把每個 Apple 的產品都定義為一個 token 時:")]),t._v(" "),v("ol",[v("li",[t._v("iPhone 14 Pro Max 1TB 深紫色")]),t._v(" "),v("li",[t._v("iPhone 14 Pro Max 1TB 金色")]),t._v(" "),v("li",[t._v("iPhone 14 Pro Max 1TB 銀色")]),t._v(" "),v("li",[t._v("iPhone 14 Pro Max 1TB 太空黑色")])]),t._v(" "),v("p",[t._v("如上,可以把不同型號、不同儲存空間大小、不同顏色的組合都設定成一個獨立的 token。\n假設本次發佈會只有以四款為主,則就會在當前的 ERC1155 中產生四種不同的 token ID,每一個 token ID 的存量就是 Apple 公司生產的庫存。")]),t._v(" "),v("p",[t._v("此時每個買到不同手機的人,他的帳戶就會多一一個對應 token ID 的 ERC1155 token,就好比你可以持有多個「ERC20 的代幣一樣」")]),t._v(" "),v("p",[t._v("而今天 Apple 為了做慈善,拿了一隻「iPhone 14 Pro Max 1TB 深紫色」上面有 Tim Cook 的簽名,並拿去拍賣。這個時候因為上面多了「Tim Cook 的簽名」,因此這個 token 就不是一般的「iPhone 14 Pro Max 1TB 深紫色」。")]),t._v(" "),v("p",[t._v("這時候我們會在合約中發布一個新的 token ID 象徵著這隻獨一無二的 iPhone,僅此一隻,如果對 NFT 敏感的同學一定會說,啊這是「ERC721」。")]),t._v(" "),v("h2",{attrs:{id:"mmorpg"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#mmorpg"}},[t._v("#")]),t._v(" MMORPG")]),t._v(" "),v("p",[t._v("在遊戲裡更是如此,當玩家進入遊戲的時候,他所建立的角色可以被做成獨一無二的 token ID 用來表示獨特性,但他打怪獲得的裝備,基本上別人也能打到,這時候就可以用非唯一的數量來發布。")]),t._v(" "),v("table",[v("thead",[v("tr",[v("th",[t._v("類型")]),t._v(" "),v("th",[t._v("性質")]),t._v(" "),v("th",[t._v("數量")])])]),t._v(" "),v("tbody",[v("tr",[v("td",[t._v("角色")]),t._v(" "),v("td",[t._v("唯一,如同身分證")]),t._v(" "),v("td",[t._v("1")])]),t._v(" "),v("tr",[v("td",[t._v("裝備")]),t._v(" "),v("td",[t._v("不唯一,只要夠肝,人人都能打到")]),t._v(" "),v("td",[t._v("N")])]),t._v(" "),v("tr",[v("td",[t._v("課金皮膚或裝備特效")]),t._v(" "),v("td",[t._v("不唯一,只要肯花錢,人人都能買到")]),t._v(" "),v("td",[t._v("N")])])])]),t._v(" "),v("p",[t._v("如果用 ERC20,便無法表現出「角色」的特性,需要 ERC721 來解決。\n若改用 ERC721,則無法表現出「裝備」與「課金皮膚、裝備、特效」的特性,需要 ERC20 來解決。")]),t._v(" "),v("p",[t._v("而我全都要的 ERC1155 就能夠取雙方的優點於一身,同時讓 ERC20 & ERC721 共存,這也是多元代幣標準的真正含義。")])])}),[],!1,null,null,null);v.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[43],{363:function(t,v,_){"use strict";_.r(v);var o=_(17),e=Object(o.a)({},(function(){var t=this,v=t._self._c;return v("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[v("h1",{attrs:{id:"erc1155-的案例"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#erc1155-的案例"}},[t._v("#")]),t._v(" ERC1155 的案例")]),t._v(" "),v("p",[t._v("昨天我們講完了 ERC1155 的標準介面,今天來看看有哪些實際的例子是能套用 ERC1155 的吧!")]),t._v(" "),v("h2",{attrs:{id:"apple-全家桶"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#apple-全家桶"}},[t._v("#")]),t._v(" Apple 全家桶")]),t._v(" "),v("p",[t._v("什麼?你說 iPhone 是 ERC1155?iPad 也是?連 macbook 都是?!\n"),v("img",{attrs:{src:"https://i.imgur.com/dhq3QfA.jpg",alt:""}})]),t._v(" "),v("p",[t._v("當我們把每個 Apple 的產品都定義為一個 token 時:")]),t._v(" "),v("ol",[v("li",[t._v("iPhone 14 Pro Max 1TB 深紫色")]),t._v(" "),v("li",[t._v("iPhone 14 Pro Max 1TB 金色")]),t._v(" "),v("li",[t._v("iPhone 14 Pro Max 1TB 銀色")]),t._v(" "),v("li",[t._v("iPhone 14 Pro Max 1TB 太空黑色")])]),t._v(" "),v("p",[t._v("如上,可以把不同型號、不同儲存空間大小、不同顏色的組合都設定成一個獨立的 token。\n假設本次發佈會只有以四款為主,則就會在當前的 ERC1155 中產生四種不同的 token ID,每一個 token ID 的存量就是 Apple 公司生產的庫存。")]),t._v(" "),v("p",[t._v("此時每個買到不同手機的人,他的帳戶就會多一一個對應 token ID 的 ERC1155 token,就好比你可以持有多個「ERC20 的代幣一樣」")]),t._v(" "),v("p",[t._v("而今天 Apple 為了做慈善,拿了一隻「iPhone 14 Pro Max 1TB 深紫色」上面有 Tim Cook 的簽名,並拿去拍賣。這個時候因為上面多了「Tim Cook 的簽名」,因此這個 token 就不是一般的「iPhone 14 Pro Max 1TB 深紫色」。")]),t._v(" "),v("p",[t._v("這時候我們會在合約中發布一個新的 token ID 象徵著這隻獨一無二的 iPhone,僅此一隻,如果對 NFT 敏感的同學一定會說,啊這是「ERC721」。")]),t._v(" "),v("h2",{attrs:{id:"mmorpg"}},[v("a",{staticClass:"header-anchor",attrs:{href:"#mmorpg"}},[t._v("#")]),t._v(" MMORPG")]),t._v(" "),v("p",[t._v("在遊戲裡更是如此,當玩家進入遊戲的時候,他所建立的角色可以被做成獨一無二的 token ID 用來表示獨特性,但他打怪獲得的裝備,基本上別人也能打到,這時候就可以用非唯一的數量來發布。")]),t._v(" "),v("table",[v("thead",[v("tr",[v("th",[t._v("類型")]),t._v(" "),v("th",[t._v("性質")]),t._v(" "),v("th",[t._v("數量")])])]),t._v(" "),v("tbody",[v("tr",[v("td",[t._v("角色")]),t._v(" "),v("td",[t._v("唯一,如同身分證")]),t._v(" "),v("td",[t._v("1")])]),t._v(" "),v("tr",[v("td",[t._v("裝備")]),t._v(" "),v("td",[t._v("不唯一,只要夠肝,人人都能打到")]),t._v(" "),v("td",[t._v("N")])]),t._v(" "),v("tr",[v("td",[t._v("課金皮膚或裝備特效")]),t._v(" "),v("td",[t._v("不唯一,只要肯花錢,人人都能買到")]),t._v(" "),v("td",[t._v("N")])])])]),t._v(" "),v("p",[t._v("如果用 ERC20,便無法表現出「角色」的特性,需要 ERC721 來解決。\n若改用 ERC721,則無法表現出「裝備」與「課金皮膚、裝備、特效」的特性,需要 ERC20 來解決。")]),t._v(" "),v("p",[t._v("而我全都要的 ERC1155 就能夠取雙方的優點於一身,同時讓 ERC20 & ERC721 共存,這也是多元代幣標準的真正含義。")])])}),[],!1,null,null,null);v.default=e.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/44.6d57de51.js b/.vuepress/dist/assets/js/44.df717947.js similarity index 98% rename from .vuepress/dist/assets/js/44.6d57de51.js rename to .vuepress/dist/assets/js/44.df717947.js index 75acbc9..57ca045 100644 --- a/.vuepress/dist/assets/js/44.6d57de51.js +++ b/.vuepress/dist/assets/js/44.df717947.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[44],{365:function(t,a,r){"use strict";r.r(a);var e=r(17),s=Object(e.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"poap-proof-of-attendance-protocol-參與證明"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#poap-proof-of-attendance-protocol-參與證明"}},[t._v("#")]),t._v(" POAP - Proof Of Attendance Protocol 參與證明")]),t._v(" "),a("p",[t._v("POAP 被設計出來作為一種數位回憶,在他的格式中記錄了「該活動的名字」、「時間」、「地點」、「紀念圖」等資訊。\n雖然也是使用 ERC721 NFT 的標準為基底,但他加上了些許的限制,比如說 POAP 只發給參加活動的參與者,申請 POAP 的發放者必須承擔起責任檢查領取的人是否真的有參與活動。")]),t._v(" "),a("h2",{attrs:{id:"使用流程"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#使用流程"}},[t._v("#")]),t._v(" 使用流程")]),t._v(" "),a("p",[t._v("活動發放者需要先去 POAP 平台上申請,需要先填寫:")]),t._v(" "),a("ol",[a("li",[t._v("活動名字與資訊")]),t._v(" "),a("li",[t._v("活動地點")]),t._v(" "),a("li",[t._v("發放的時間區間(只有在這個區間內才能領到該活動的 POAP)")]),t._v(" "),a("li",[t._v("活動的紀念照片(會作為該 POAP 的顯示圖片)")])]),t._v(" "),a("p",[t._v("在申請以後,POAP 組織會審核這個活動,如無問題,通常在 24 小時內就能獲得批准。")]),t._v(" "),a("p",[t._v("之所以多了一個審核機制是因為目前 POAP 發行在 xDai 區塊鏈上,如我們之前提到的燃料費用問題一樣,POAP 平台是免費提供這個服務,因此燃料費是由他們那邊所支付,為了避免濫用與惡意使用,因此才需要多做審核。")]),t._v(" "),a("p",[t._v("再通過審核後,就只需要活動的參加者去申請該 POAP 即可獲得。")]),t._v(" "),a("h2",{attrs:{id:"例子"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#例子"}},[t._v("#")]),t._v(" 例子")]),t._v(" "),a("h3",{attrs:{id:"參與專案開發的證明"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#參與專案開發的證明"}},[t._v("#")]),t._v(" 參與專案開發的證明")]),t._v(" "),a("p",[a("a",{attrs:{href:"https://www.gitpoap.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("GitPOAP 服務"),a("OutboundLink")],1),t._v(",這個服務連結了你的錢包與 GitHub/GitLab 帳號,當你貢獻過有參與 GitPOAP 服務的專案時,他會發行對應的 POAP 給你,證明你在該年度有貢獻過,以資鼓勵。")]),t._v(" "),a("p",[t._v("如下圖,是我在 2018~2019 年貢獻過 solidity 與 go-ethereum 兩個專案所獲得的 POAP。")]),t._v(" "),a("p",[a("img",{attrs:{src:"https://i.imgur.com/WcRtzol.png",alt:""}})]),t._v(" "),a("p",[a("img",{attrs:{src:"https://i.imgur.com/Tz4mq93.png",alt:""}})]),t._v(" "),a("h3",{attrs:{id:"捐款證明"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#捐款證明"}},[t._v("#")]),t._v(" 捐款證明")]),t._v(" "),a("p",[t._v("比如說以下的 POAP 就是在 Mainnet Merge 派對時,只要捐款到特定帳號,就能獲得這枚捐款 POAP。")]),t._v(" "),a("p",[a("img",{attrs:{src:"https://i.imgur.com/XslYY7y.png",alt:""}})]),t._v(" "),a("p",[t._v("本次捐款活動細節,可以參考以下影片: https://www.youtube.com/watch?v=ZY7eXUn7Mpo")]),t._v(" "),a("h2",{attrs:{id:"相關連結"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#相關連結"}},[t._v("#")]),t._v(" 相關連結")]),t._v(" "),a("p",[a("a",{attrs:{href:"https://poap.xyz/",target:"_blank",rel:"noopener noreferrer"}},[t._v("官網"),a("OutboundLink")],1)])])}),[],!1,null,null,null);a.default=s.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[44],{366:function(t,a,r){"use strict";r.r(a);var e=r(17),s=Object(e.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"poap-proof-of-attendance-protocol-參與證明"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#poap-proof-of-attendance-protocol-參與證明"}},[t._v("#")]),t._v(" POAP - Proof Of Attendance Protocol 參與證明")]),t._v(" "),a("p",[t._v("POAP 被設計出來作為一種數位回憶,在他的格式中記錄了「該活動的名字」、「時間」、「地點」、「紀念圖」等資訊。\n雖然也是使用 ERC721 NFT 的標準為基底,但他加上了些許的限制,比如說 POAP 只發給參加活動的參與者,申請 POAP 的發放者必須承擔起責任檢查領取的人是否真的有參與活動。")]),t._v(" "),a("h2",{attrs:{id:"使用流程"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#使用流程"}},[t._v("#")]),t._v(" 使用流程")]),t._v(" "),a("p",[t._v("活動發放者需要先去 POAP 平台上申請,需要先填寫:")]),t._v(" "),a("ol",[a("li",[t._v("活動名字與資訊")]),t._v(" "),a("li",[t._v("活動地點")]),t._v(" "),a("li",[t._v("發放的時間區間(只有在這個區間內才能領到該活動的 POAP)")]),t._v(" "),a("li",[t._v("活動的紀念照片(會作為該 POAP 的顯示圖片)")])]),t._v(" "),a("p",[t._v("在申請以後,POAP 組織會審核這個活動,如無問題,通常在 24 小時內就能獲得批准。")]),t._v(" "),a("p",[t._v("之所以多了一個審核機制是因為目前 POAP 發行在 xDai 區塊鏈上,如我們之前提到的燃料費用問題一樣,POAP 平台是免費提供這個服務,因此燃料費是由他們那邊所支付,為了避免濫用與惡意使用,因此才需要多做審核。")]),t._v(" "),a("p",[t._v("再通過審核後,就只需要活動的參加者去申請該 POAP 即可獲得。")]),t._v(" "),a("h2",{attrs:{id:"例子"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#例子"}},[t._v("#")]),t._v(" 例子")]),t._v(" "),a("h3",{attrs:{id:"參與專案開發的證明"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#參與專案開發的證明"}},[t._v("#")]),t._v(" 參與專案開發的證明")]),t._v(" "),a("p",[a("a",{attrs:{href:"https://www.gitpoap.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("GitPOAP 服務"),a("OutboundLink")],1),t._v(",這個服務連結了你的錢包與 GitHub/GitLab 帳號,當你貢獻過有參與 GitPOAP 服務的專案時,他會發行對應的 POAP 給你,證明你在該年度有貢獻過,以資鼓勵。")]),t._v(" "),a("p",[t._v("如下圖,是我在 2018~2019 年貢獻過 solidity 與 go-ethereum 兩個專案所獲得的 POAP。")]),t._v(" "),a("p",[a("img",{attrs:{src:"https://i.imgur.com/WcRtzol.png",alt:""}})]),t._v(" "),a("p",[a("img",{attrs:{src:"https://i.imgur.com/Tz4mq93.png",alt:""}})]),t._v(" "),a("h3",{attrs:{id:"捐款證明"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#捐款證明"}},[t._v("#")]),t._v(" 捐款證明")]),t._v(" "),a("p",[t._v("比如說以下的 POAP 就是在 Mainnet Merge 派對時,只要捐款到特定帳號,就能獲得這枚捐款 POAP。")]),t._v(" "),a("p",[a("img",{attrs:{src:"https://i.imgur.com/XslYY7y.png",alt:""}})]),t._v(" "),a("p",[t._v("本次捐款活動細節,可以參考以下影片: https://www.youtube.com/watch?v=ZY7eXUn7Mpo")]),t._v(" "),a("h2",{attrs:{id:"相關連結"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#相關連結"}},[t._v("#")]),t._v(" 相關連結")]),t._v(" "),a("p",[a("a",{attrs:{href:"https://poap.xyz/",target:"_blank",rel:"noopener noreferrer"}},[t._v("官網"),a("OutboundLink")],1)])])}),[],!1,null,null,null);a.default=s.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/45.0956e95c.js b/.vuepress/dist/assets/js/45.7358417c.js similarity index 99% rename from .vuepress/dist/assets/js/45.0956e95c.js rename to .vuepress/dist/assets/js/45.7358417c.js index 596dfba..9401fa0 100644 --- a/.vuepress/dist/assets/js/45.0956e95c.js +++ b/.vuepress/dist/assets/js/45.7358417c.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[45],{368:function(t,s,a){"use strict";a.r(s);var n=a(17),r=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-1"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#實例解析-proof-of-stake-書籍的捐款合約-part-1"}},[t._v("#")]),t._v(" 實例解析 - Proof of Stake 書籍的捐款合約 Part 1")]),t._v(" "),s("h2",{attrs:{id:"關於此書"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#關於此書"}},[t._v("#")]),t._v(" 關於此書")]),t._v(" "),s("p",[s("img",{attrs:{src:"https://i.imgur.com/pzgrA8F.jpg",alt:""}})]),t._v(" "),s("p",[t._v("以太坊聯合創始人 Vitalik Buterin 在 2022/8/31 宣佈他將發布一本新書「Proof of Stake」,將包含實體版(可以從各大通路買到)與數位版(一本 PDF)。書中總結了他過去十年來的各種寫作精華。")]),t._v(" "),s("p",[t._v("如果透過 gitcoin 的數位通路進行捐款,將可以獲得數位簽名版加上一個 NFT 作為回饋。")]),t._v(" "),s("p",[t._v("該募資網站: https://proofofstake.gitcoin.co")]),t._v(" "),s("h2",{attrs:{id:"捐款後的-nft"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#捐款後的-nft"}},[t._v("#")]),t._v(" 捐款後的 NFT")]),t._v(" "),s("p",[s("img",{attrs:{src:"https://i.imgur.com/bxqLltK.png",alt:""}})]),t._v(" "),s("p",[t._v("如上圖,在捐款後所獲得的 NFT 會紀錄什麼時候鑄造的、捐款多少、與合約地址。")]),t._v(" "),s("h2",{attrs:{id:"解析合約"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#解析合約"}},[t._v("#")]),t._v(" 解析合約")]),t._v(" "),s("p",[t._v("既然有了合約地址,因此接下來的幾日,我們將依序拆解這個合約,來講講捐款、鑄造等合約的內容。\n請注意,如果是輔助函式,在本系列中不會特別花力氣講解每一行的邏輯,只會提及該合約被引入的主要目的。")]),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(" "),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\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\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\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\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\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" base64"),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(" Transforms"),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("h3",{attrs:{id:"transforms-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#transforms-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("Transforms.sol")])]),t._v(" "),s("p",[s("code",[t._v("Transforms")]),t._v(" 是一個輔助合約,他提供以下幾個功能:")]),t._v(" "),s("ol",[s("li",[t._v("將簽名(signature)還原出構成的 "),s("code",[t._v("v")]),t._v(", "),s("code",[t._v("r")]),t._v(", "),s("code",[t._v("s")]),t._v(" 三個部分。")]),t._v(" "),s("li",[t._v("把位址(address)轉成字串(string)")]),t._v(" "),s("li",[t._v("將一個位元組(bytes1)轉成字元(依然是 bytes1,但轉成可視範圍)")])]),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: MIT")]),t._v("\n\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("Transforms")]),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("splitSignature")]),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(" sig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pure")]),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("(")]),t._v("\n "),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("\n "),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("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),t._v(" s\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 keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sig"),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("65")]),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("assembly")]),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("// first 32 bytes, after the length prefix.")]),t._v("\n r "),s("span",{pre:!0,attrs:{class:"token operator"}},[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("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),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("// second 32 bytes.")]),t._v("\n s "),s("span",{pre:!0,attrs:{class:"token operator"}},[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("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("64")]),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("// final byte (first byte of the next 32 bytes).")]),t._v("\n v "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),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 function"}},[t._v("mload")]),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("(")]),t._v("sig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("96")]),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("return")]),t._v(" "),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 "),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 TYPE LOGIC\n //////////////////////////////////////////////////////////////*/")]),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("toAsciiString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" x"),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(" s "),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("40")]),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("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(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),s("span",{pre:!0,attrs:{class:"token operator"}},[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 builtin"}},[t._v("bytes1")]),t._v(" b "),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 builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint160")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),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 punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("**")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("19")]),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(")")]),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(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes1")]),t._v(" hi "),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("(")]),t._v("b"),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("16")]),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("bytes1")]),t._v(" lo "),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("(")]),t._v("b"),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("16")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hi"),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"),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(" 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(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("char")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n s"),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(" 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(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("char")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lo"),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("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("s"),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("char")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes1")]),t._v(" b"),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("bytes1")]),t._v(" c"),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("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),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("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),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("(")]),t._v("b"),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("0x30")]),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("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),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("(")]),t._v("b"),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("0x57")]),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:"base64-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#base64-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("base64.sol")])]),t._v(" "),s("p",[t._v("關於 base64 格式的細節,請"),s("a",{attrs:{href:"https://zh.wikipedia.org/zh-tw/Base64",target:"_blank",rel:"noopener noreferrer"}},[t._v("參考維基百科"),s("OutboundLink")],1)]),t._v(" "),s("p",[t._v("提供對 base64 格式的編碼與解碼函式:")]),t._v(" "),s("ol",[s("li",[s("code",[t._v("encode")]),t._v(":將一段資料(bytes 格式)編碼成一串 base64 格式的字串(string)")]),t._v(" "),s("li",[s("code",[t._v("decode")]),t._v(":將 base64 格式的字串(string)解碼成原始資料(bytes)")])]),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.6.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("/// @title Base64")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/// @author Brecht Devos - ")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/// @notice Provides functions for encoding/decoding base64")]),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("Base64")]),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("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" TABLE_ENCODE "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'")]),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("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" TABLE_DECODE "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" hex"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0000000000000000000000000000000000000000000000000000000000000000"')]),t._v("\n hex"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"00000000000000000000003e0000003f3435363738393a3b3c3d000000000000"')]),t._v("\n hex"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"00000102030405060708090a0b0c0d0e0f101112131415161718190000000000"')]),t._v("\n hex"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"001a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132330000000000"')]),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("encode")]),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(" data"),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("data"),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 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\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// load the table into memory")]),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(" table "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" TABLE_ENCODE"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// multiply by 4/3 rounded up")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" encodedLen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),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("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(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),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("// add some extra buffer at the end required for the writing")]),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(" result "),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("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("encodedLen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),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("assembly")]),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("// set the actual output length")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mstore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" encodedLen"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prepare the lookup table")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" tablePtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("table"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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("// input ptr")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" dataPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" data\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" endPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dataPtr"),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("data"),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("// result ptr, jump over length")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" resultPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),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("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// run over the input, 3 bytes at a time")]),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 punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("lt")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dataPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" endPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),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 comment"}},[t._v("// read 3 bytes")]),t._v("\n dataPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dataPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" input "),s("span",{pre:!0,attrs:{class:"token operator"}},[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("dataPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// write 4 characters")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mstore8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),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("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("18")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" input"),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 number"}},[t._v("0x3F")]),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 resultPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 function"}},[t._v("mstore8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),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("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" input"),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 number"}},[t._v("0x3F")]),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 resultPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 function"}},[t._v("mstore8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),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("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" input"),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 number"}},[t._v("0x3F")]),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 resultPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 function"}},[t._v("mstore8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),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("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" input"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x3F")]),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 resultPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// padding with '='")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mod")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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("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 number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mstore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sub")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("240")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x3d3d")]),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("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mstore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sub")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("248")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x3d")]),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 punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" result"),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("decode")]),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(" _data"),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("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(" data "),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("(")]),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\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("data"),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 keyword"}},[t._v("return")]),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("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 keyword"}},[t._v("require")]),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("length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),t._v(" "),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('"invalid base64 decoder input"')]),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("// load the table into memory")]),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(" table "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" TABLE_DECODE"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// every 4 characters represent 3 bytes")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" decodedLen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),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("length "),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(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add some extra buffer at the end required for the writing")]),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(" result "),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("decodedLen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),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("assembly")]),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("// padding with '='")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" lastBytes "),s("span",{pre:!0,attrs:{class:"token operator"}},[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("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),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 function"}},[t._v("mload")]),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(")")]),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 function"}},[t._v("eq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lastBytes"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xFF")]),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 number"}},[t._v("0x3d")]),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 decodedLen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sub")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("decodedLen"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("eq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lastBytes"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xFFFF")]),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 number"}},[t._v("0x3d3d")]),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 decodedLen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sub")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("decodedLen"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 comment"}},[t._v("// set the actual output length")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mstore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" decodedLen"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prepare the lookup table")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" tablePtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("table"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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("// input ptr")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" dataPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" data\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" endPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dataPtr"),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("data"),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("// result ptr, jump over length")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" resultPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),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("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// run over the input, 4 characters at a time")]),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 punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("lt")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dataPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" endPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),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 comment"}},[t._v("// read 4 characters")]),t._v("\n dataPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dataPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 keyword"}},[t._v("let")]),t._v(" input "),s("span",{pre:!0,attrs:{class:"token operator"}},[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("dataPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// write 3 bytes")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" output "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("18")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mload")]),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("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("24")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" input"),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 number"}},[t._v("0xFF")]),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 number"}},[t._v("0xFF")]),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("shl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mload")]),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("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("16")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" input"),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 number"}},[t._v("0xFF")]),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 number"}},[t._v("0xFF")]),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 function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mload")]),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("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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(" input"),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 number"}},[t._v("0xFF")]),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 number"}},[t._v("0xFF")]),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("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mload")]),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("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" input "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xFF")]),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 number"}},[t._v("0xFF")]),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 function"}},[t._v("mstore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("232")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n resultPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),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("return")]),t._v(" result"),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=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[45],{365:function(t,s,a){"use strict";a.r(s);var n=a(17),r=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-1"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#實例解析-proof-of-stake-書籍的捐款合約-part-1"}},[t._v("#")]),t._v(" 實例解析 - Proof of Stake 書籍的捐款合約 Part 1")]),t._v(" "),s("h2",{attrs:{id:"關於此書"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#關於此書"}},[t._v("#")]),t._v(" 關於此書")]),t._v(" "),s("p",[s("img",{attrs:{src:"https://i.imgur.com/pzgrA8F.jpg",alt:""}})]),t._v(" "),s("p",[t._v("以太坊聯合創始人 Vitalik Buterin 在 2022/8/31 宣佈他將發布一本新書「Proof of Stake」,將包含實體版(可以從各大通路買到)與數位版(一本 PDF)。書中總結了他過去十年來的各種寫作精華。")]),t._v(" "),s("p",[t._v("如果透過 gitcoin 的數位通路進行捐款,將可以獲得數位簽名版加上一個 NFT 作為回饋。")]),t._v(" "),s("p",[t._v("該募資網站: https://proofofstake.gitcoin.co")]),t._v(" "),s("h2",{attrs:{id:"捐款後的-nft"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#捐款後的-nft"}},[t._v("#")]),t._v(" 捐款後的 NFT")]),t._v(" "),s("p",[s("img",{attrs:{src:"https://i.imgur.com/bxqLltK.png",alt:""}})]),t._v(" "),s("p",[t._v("如上圖,在捐款後所獲得的 NFT 會紀錄什麼時候鑄造的、捐款多少、與合約地址。")]),t._v(" "),s("h2",{attrs:{id:"解析合約"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#解析合約"}},[t._v("#")]),t._v(" 解析合約")]),t._v(" "),s("p",[t._v("既然有了合約地址,因此接下來的幾日,我們將依序拆解這個合約,來講講捐款、鑄造等合約的內容。\n請注意,如果是輔助函式,在本系列中不會特別花力氣講解每一行的邏輯,只會提及該合約被引入的主要目的。")]),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(" "),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\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\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\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\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\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" base64"),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(" Transforms"),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("h3",{attrs:{id:"transforms-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#transforms-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("Transforms.sol")])]),t._v(" "),s("p",[s("code",[t._v("Transforms")]),t._v(" 是一個輔助合約,他提供以下幾個功能:")]),t._v(" "),s("ol",[s("li",[t._v("將簽名(signature)還原出構成的 "),s("code",[t._v("v")]),t._v(", "),s("code",[t._v("r")]),t._v(", "),s("code",[t._v("s")]),t._v(" 三個部分。")]),t._v(" "),s("li",[t._v("把位址(address)轉成字串(string)")]),t._v(" "),s("li",[t._v("將一個位元組(bytes1)轉成字元(依然是 bytes1,但轉成可視範圍)")])]),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: MIT")]),t._v("\n\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("Transforms")]),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("splitSignature")]),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(" sig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("internal")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pure")]),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("(")]),t._v("\n "),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("\n "),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("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes32")]),t._v(" s\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 keyword"}},[t._v("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sig"),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("65")]),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("assembly")]),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("// first 32 bytes, after the length prefix.")]),t._v("\n r "),s("span",{pre:!0,attrs:{class:"token operator"}},[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("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),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("// second 32 bytes.")]),t._v("\n s "),s("span",{pre:!0,attrs:{class:"token operator"}},[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("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("64")]),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("// final byte (first byte of the next 32 bytes).")]),t._v("\n v "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),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 function"}},[t._v("mload")]),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("(")]),t._v("sig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("96")]),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("return")]),t._v(" "),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 "),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 TYPE LOGIC\n //////////////////////////////////////////////////////////////*/")]),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("toAsciiString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" x"),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(" s "),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("40")]),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("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(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),s("span",{pre:!0,attrs:{class:"token operator"}},[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 builtin"}},[t._v("bytes1")]),t._v(" b "),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 builtin"}},[t._v("uint256")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint160")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),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 punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("**")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("19")]),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(")")]),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(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes1")]),t._v(" hi "),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("(")]),t._v("b"),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("16")]),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("bytes1")]),t._v(" lo "),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("(")]),t._v("b"),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("16")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hi"),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"),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(" 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(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("char")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hi"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n s"),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(" 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(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("char")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lo"),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("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("s"),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("char")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bytes1")]),t._v(" b"),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("bytes1")]),t._v(" c"),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("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),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("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),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("(")]),t._v("b"),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("0x30")]),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("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),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("(")]),t._v("b"),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("0x57")]),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:"base64-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#base64-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("base64.sol")])]),t._v(" "),s("p",[t._v("關於 base64 格式的細節,請"),s("a",{attrs:{href:"https://zh.wikipedia.org/zh-tw/Base64",target:"_blank",rel:"noopener noreferrer"}},[t._v("參考維基百科"),s("OutboundLink")],1)]),t._v(" "),s("p",[t._v("提供對 base64 格式的編碼與解碼函式:")]),t._v(" "),s("ol",[s("li",[s("code",[t._v("encode")]),t._v(":將一段資料(bytes 格式)編碼成一串 base64 格式的字串(string)")]),t._v(" "),s("li",[s("code",[t._v("decode")]),t._v(":將 base64 格式的字串(string)解碼成原始資料(bytes)")])]),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.6.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("/// @title Base64")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/// @author Brecht Devos - ")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/// @notice Provides functions for encoding/decoding base64")]),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("Base64")]),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("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" TABLE_ENCODE "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'")]),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("internal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("constant")]),t._v(" TABLE_DECODE "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" hex"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0000000000000000000000000000000000000000000000000000000000000000"')]),t._v("\n hex"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"00000000000000000000003e0000003f3435363738393a3b3c3d000000000000"')]),t._v("\n hex"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"00000102030405060708090a0b0c0d0e0f101112131415161718190000000000"')]),t._v("\n hex"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"001a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132330000000000"')]),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("encode")]),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(" data"),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("data"),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 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\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// load the table into memory")]),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(" table "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" TABLE_ENCODE"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// multiply by 4/3 rounded up")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" encodedLen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),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("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(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),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("// add some extra buffer at the end required for the writing")]),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(" result "),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("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("encodedLen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),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("assembly")]),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("// set the actual output length")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mstore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" encodedLen"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prepare the lookup table")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" tablePtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("table"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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("// input ptr")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" dataPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" data\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" endPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dataPtr"),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("data"),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("// result ptr, jump over length")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" resultPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),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("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// run over the input, 3 bytes at a time")]),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 punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("lt")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dataPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" endPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),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 comment"}},[t._v("// read 3 bytes")]),t._v("\n dataPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dataPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" input "),s("span",{pre:!0,attrs:{class:"token operator"}},[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("dataPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// write 4 characters")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mstore8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),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("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("18")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" input"),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 number"}},[t._v("0x3F")]),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 resultPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 function"}},[t._v("mstore8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),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("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" input"),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 number"}},[t._v("0x3F")]),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 resultPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 function"}},[t._v("mstore8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),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("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" input"),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 number"}},[t._v("0x3F")]),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 resultPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 function"}},[t._v("mstore8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),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("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" input"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x3F")]),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 resultPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// padding with '='")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mod")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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("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 number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mstore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sub")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("240")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x3d3d")]),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("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mstore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sub")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("248")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x3d")]),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 punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" result"),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("decode")]),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(" _data"),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("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(" data "),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("(")]),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\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("data"),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 keyword"}},[t._v("return")]),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("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 keyword"}},[t._v("require")]),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("length "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),t._v(" "),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('"invalid base64 decoder input"')]),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("// load the table into memory")]),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(" table "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" TABLE_DECODE"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// every 4 characters represent 3 bytes")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" decodedLen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),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("length "),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(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add some extra buffer at the end required for the writing")]),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(" result "),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("decodedLen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),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("assembly")]),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("// padding with '='")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" lastBytes "),s("span",{pre:!0,attrs:{class:"token operator"}},[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("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),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 function"}},[t._v("mload")]),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(")")]),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 function"}},[t._v("eq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lastBytes"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xFF")]),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 number"}},[t._v("0x3d")]),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 decodedLen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sub")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("decodedLen"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("eq")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lastBytes"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xFFFF")]),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 number"}},[t._v("0x3d3d")]),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 decodedLen "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sub")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("decodedLen"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 comment"}},[t._v("// set the actual output length")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mstore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" decodedLen"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prepare the lookup table")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" tablePtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("table"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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("// input ptr")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" dataPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" data\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" endPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dataPtr"),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("data"),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("// result ptr, jump over length")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" resultPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),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("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// run over the input, 4 characters at a time")]),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 punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("lt")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dataPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" endPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),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 comment"}},[t._v("// read 4 characters")]),t._v("\n dataPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dataPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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 keyword"}},[t._v("let")]),t._v(" input "),s("span",{pre:!0,attrs:{class:"token operator"}},[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("dataPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// write 3 bytes")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" output "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("18")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mload")]),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("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("24")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" input"),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 number"}},[t._v("0xFF")]),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 number"}},[t._v("0xFF")]),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("shl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mload")]),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("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("16")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" input"),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 number"}},[t._v("0xFF")]),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 number"}},[t._v("0xFF")]),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 function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mload")]),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("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[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(" input"),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 number"}},[t._v("0xFF")]),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 number"}},[t._v("0xFF")]),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("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mload")]),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("(")]),t._v("tablePtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("and")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" input "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xFF")]),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 number"}},[t._v("0xFF")]),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 function"}},[t._v("mstore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("shl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("232")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n resultPtr "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resultPtr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),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("return")]),t._v(" result"),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=r.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/46.7d8be4f3.js b/.vuepress/dist/assets/js/46.bdb025a8.js similarity index 99% rename from .vuepress/dist/assets/js/46.7d8be4f3.js rename to .vuepress/dist/assets/js/46.bdb025a8.js index 635e675..901e5ab 100644 --- a/.vuepress/dist/assets/js/46.7d8be4f3.js +++ b/.vuepress/dist/assets/js/46.bdb025a8.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[46],{366: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/.vuepress/dist/assets/js/47.a93f348e.js b/.vuepress/dist/assets/js/47.f895a2cf.js similarity index 99% rename from .vuepress/dist/assets/js/47.a93f348e.js rename to .vuepress/dist/assets/js/47.f895a2cf.js index 268fa3b..cc09423 100644 --- a/.vuepress/dist/assets/js/47.a93f348e.js +++ b/.vuepress/dist/assets/js/47.f895a2cf.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/.vuepress/dist/assets/js/48.1f5224ec.js b/.vuepress/dist/assets/js/48.e34e19d6.js similarity index 99% rename from .vuepress/dist/assets/js/48.1f5224ec.js rename to .vuepress/dist/assets/js/48.e34e19d6.js index 39e58bd..b604c5a 100644 --- a/.vuepress/dist/assets/js/48.1f5224ec.js +++ b/.vuepress/dist/assets/js/48.e34e19d6.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[48],{374: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-4"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#實例解析-proof-of-stake-書籍的捐款合約-part-4"}},[t._v("#")]),t._v(" 實例解析 - Proof of Stake 書籍的捐款合約 Part 4")]),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\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"),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("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:"address-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#address-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("Address.sol")])]),t._v(" "),s("p",[t._v("由於 NFT 的接收方可能為一個「合約地址」,為了避免 NFT 被轉移到一個無法再次轉出的合約中,因此需要對每個接收者的位址進行檢查。")]),t._v(" "),s("p",[t._v("而無法再次轉出的理由是,因為對 NFT 的操作,都是要對該 NFT 合約中的函式進行呼叫,因此若該接收者合約無法對其他合約進行相關的操作,該 NFT 將永久性地被留在接收者手上。")]),t._v(" "),s("p",[s("code",[t._v("Address")]),t._v(" 函式庫提供了一些輔助函式,用來協助對位址型態("),s("code",[t._v("Address Type")]),t._v(")的操作。")]),t._v(" "),s("ol",[s("li",[s("code",[t._v("function isContract(address account) internal view returns (bool)")]),t._v(":檢查該位址是否為一個合約,請特別注意,回傳「真(true)」保證了該位址是個合約;但回傳「假(false)」時不代表該位址就是個 EOA (externally-owned account),可能還有以下幾種可能:「正在被建立中的合約」、「預定會被部署合約的位址」、「曾經是個合約,但已經被銷毀」。 "),s("strong",[t._v("實際上在這個例子中,它引入 Address.sol 只為了這個函式")])]),t._v(" "),s("li",[s("code",[t._v("sendValue")]),t._v(":用來取代 Solidity 內建的 "),s("code",[t._v("transfer")]),t._v(" 函式。")]),t._v(" "),s("li",[s("code",[t._v("functionCall")]),t._v(":用來取代 Solidity 內建的 "),s("code",[t._v("low level call")]),t._v(" 函式。")]),t._v(" "),s("li",[s("code",[t._v("functionCallWithValue")]),t._v(":為 "),s("code",[t._v("low level call")]),t._v(" 加上可以附帶 wei 的函式。")]),t._v(" "),s("li",[s("code",[t._v("functionStaticCall")]),t._v(":用來取代 Solidity 內建的 "),s("code",[t._v("low level staticcall")]),t._v(" 函式。")]),t._v(" "),s("li",[s("code",[t._v("functionDelegateCall")]),t._v(":用來取代 Solidity 內建的 "),s("code",[t._v("low level delegatecall")]),t._v(" 函式。")]),t._v(" "),s("li",[s("code",[t._v("verifyCallResult")]),t._v(":用來驗證上面幾個 "),s("code",[t._v("call")]),t._v(" 系列的函式是否執行成功。若失敗,則觸發 "),s("code",[t._v("revert")]),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 Collection of functions related to the address type\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("Address")]),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("/**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\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("isContract")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" account"),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("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("// This method relies on extcodesize, which returns 0 for contracts in")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// construction, since the code is only stored at the end of the")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// constructor execution.")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" size"),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 size "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("extcodesize")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("account"),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(" size "),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\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\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("sendValue")]),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("payable")]),t._v(" recipient"),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(" amount"),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 keyword"}},[t._v("require")]),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(".")]),t._v("balance "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">=")]),t._v(" amount"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Address: insufficient balance"')]),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 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(" recipient"),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(" amount"),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("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("success"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Address: unable to send value, recipient may have reverted"')]),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 Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\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("functionCall")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),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(" data"),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("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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("functionCall")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("target"),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 string"}},[t._v('"Address: low-level call failed"')]),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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\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("functionCall")]),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(" target"),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"),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(" errorMessage\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(" "),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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("functionCallWithValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("target"),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 number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" errorMessage"),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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\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("functionCallWithValue")]),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(" target"),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"),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\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(" "),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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("functionCallWithValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("target"),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(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Address: low-level call with value failed"')]),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 Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\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("functionCallWithValue")]),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(" target"),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"),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 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(" errorMessage\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(" "),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 keyword"}},[t._v("require")]),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(".")]),t._v("balance "),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(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Address: insufficient balance for call"')]),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 function"}},[t._v("isContract")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("target"),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('"Address: call to non-contract"')]),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 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 builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" returndata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" target"),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(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("verifyCallResult")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("success"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" returndata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" errorMessage"),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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\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("functionStaticCall")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),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(" data"),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("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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("functionStaticCall")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("target"),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 string"}},[t._v('"Address: low-level static call failed"')]),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 Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\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("functionStaticCall")]),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(" target"),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"),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(" errorMessage\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(" "),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 keyword"}},[t._v("require")]),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("(")]),t._v("target"),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('"Address: static call to non-contract"')]),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 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 builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" returndata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("staticcall")]),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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("verifyCallResult")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("success"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" returndata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" errorMessage"),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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\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("functionDelegateCall")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),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(" data"),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("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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("functionDelegateCall")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("target"),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 string"}},[t._v('"Address: low-level delegate call failed"')]),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 Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\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("functionDelegateCall")]),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(" target"),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"),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(" errorMessage\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(" "),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 keyword"}},[t._v("require")]),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("(")]),t._v("target"),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('"Address: delegate call to non-contract"')]),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 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 builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" returndata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("delegatecall")]),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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("verifyCallResult")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("success"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" returndata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" errorMessage"),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 Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\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("verifyCallResult")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),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("\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(" returndata"),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(" errorMessage\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(" "),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("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 keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),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("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" returndata"),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 comment"}},[t._v("// Look for revert reason and bubble it up if present")]),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("returndata"),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 comment"}},[t._v("// The easiest way to bubble the revert reason is using memory via assembly")]),t._v("\n\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("let")]),t._v(" returndata_size "),s("span",{pre:!0,attrs:{class:"token operator"}},[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("returndata"),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(" returndata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" returndata_size"),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("revert")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("errorMessage"),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("\n")])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[48],{370: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-4"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#實例解析-proof-of-stake-書籍的捐款合約-part-4"}},[t._v("#")]),t._v(" 實例解析 - Proof of Stake 書籍的捐款合約 Part 4")]),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\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"),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("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:"address-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#address-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("Address.sol")])]),t._v(" "),s("p",[t._v("由於 NFT 的接收方可能為一個「合約地址」,為了避免 NFT 被轉移到一個無法再次轉出的合約中,因此需要對每個接收者的位址進行檢查。")]),t._v(" "),s("p",[t._v("而無法再次轉出的理由是,因為對 NFT 的操作,都是要對該 NFT 合約中的函式進行呼叫,因此若該接收者合約無法對其他合約進行相關的操作,該 NFT 將永久性地被留在接收者手上。")]),t._v(" "),s("p",[s("code",[t._v("Address")]),t._v(" 函式庫提供了一些輔助函式,用來協助對位址型態("),s("code",[t._v("Address Type")]),t._v(")的操作。")]),t._v(" "),s("ol",[s("li",[s("code",[t._v("function isContract(address account) internal view returns (bool)")]),t._v(":檢查該位址是否為一個合約,請特別注意,回傳「真(true)」保證了該位址是個合約;但回傳「假(false)」時不代表該位址就是個 EOA (externally-owned account),可能還有以下幾種可能:「正在被建立中的合約」、「預定會被部署合約的位址」、「曾經是個合約,但已經被銷毀」。 "),s("strong",[t._v("實際上在這個例子中,它引入 Address.sol 只為了這個函式")])]),t._v(" "),s("li",[s("code",[t._v("sendValue")]),t._v(":用來取代 Solidity 內建的 "),s("code",[t._v("transfer")]),t._v(" 函式。")]),t._v(" "),s("li",[s("code",[t._v("functionCall")]),t._v(":用來取代 Solidity 內建的 "),s("code",[t._v("low level call")]),t._v(" 函式。")]),t._v(" "),s("li",[s("code",[t._v("functionCallWithValue")]),t._v(":為 "),s("code",[t._v("low level call")]),t._v(" 加上可以附帶 wei 的函式。")]),t._v(" "),s("li",[s("code",[t._v("functionStaticCall")]),t._v(":用來取代 Solidity 內建的 "),s("code",[t._v("low level staticcall")]),t._v(" 函式。")]),t._v(" "),s("li",[s("code",[t._v("functionDelegateCall")]),t._v(":用來取代 Solidity 內建的 "),s("code",[t._v("low level delegatecall")]),t._v(" 函式。")]),t._v(" "),s("li",[s("code",[t._v("verifyCallResult")]),t._v(":用來驗證上面幾個 "),s("code",[t._v("call")]),t._v(" 系列的函式是否執行成功。若失敗,則觸發 "),s("code",[t._v("revert")]),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 Collection of functions related to the address type\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("Address")]),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("/**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\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("isContract")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" account"),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("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("// This method relies on extcodesize, which returns 0 for contracts in")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// construction, since the code is only stored at the end of the")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// constructor execution.")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint256")]),t._v(" size"),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 size "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("extcodesize")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("account"),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(" size "),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\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\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("sendValue")]),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("payable")]),t._v(" recipient"),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(" amount"),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 keyword"}},[t._v("require")]),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(".")]),t._v("balance "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">=")]),t._v(" amount"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Address: insufficient balance"')]),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 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(" recipient"),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(" amount"),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("require")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("success"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Address: unable to send value, recipient may have reverted"')]),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 Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\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("functionCall")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),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(" data"),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("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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("functionCall")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("target"),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 string"}},[t._v('"Address: low-level call failed"')]),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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\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("functionCall")]),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(" target"),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"),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(" errorMessage\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(" "),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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("functionCallWithValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("target"),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 number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" errorMessage"),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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\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("functionCallWithValue")]),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(" target"),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"),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\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(" "),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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("functionCallWithValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("target"),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(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Address: low-level call with value failed"')]),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 Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\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("functionCallWithValue")]),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(" target"),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"),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 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(" errorMessage\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(" "),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 keyword"}},[t._v("require")]),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(".")]),t._v("balance "),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(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Address: insufficient balance for call"')]),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 function"}},[t._v("isContract")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("target"),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('"Address: call to non-contract"')]),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 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 builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" returndata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" target"),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(" value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("verifyCallResult")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("success"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" returndata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" errorMessage"),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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\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("functionStaticCall")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),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(" data"),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("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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("functionStaticCall")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("target"),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 string"}},[t._v('"Address: low-level static call failed"')]),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 Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\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("functionStaticCall")]),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(" target"),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"),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(" errorMessage\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(" "),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 keyword"}},[t._v("require")]),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("(")]),t._v("target"),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('"Address: static call to non-contract"')]),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 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 builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" returndata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("staticcall")]),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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("verifyCallResult")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("success"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" returndata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" errorMessage"),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 Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\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("functionDelegateCall")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("address")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),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(" data"),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("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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("functionDelegateCall")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("target"),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 string"}},[t._v('"Address: low-level delegate call failed"')]),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 Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\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("functionDelegateCall")]),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(" target"),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"),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(" errorMessage\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(" "),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 keyword"}},[t._v("require")]),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("(")]),t._v("target"),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('"Address: delegate call to non-contract"')]),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 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 builtin"}},[t._v("bytes")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("memory")]),t._v(" returndata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("delegatecall")]),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 keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("verifyCallResult")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("success"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" returndata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" errorMessage"),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 Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\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("verifyCallResult")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),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("\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(" returndata"),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(" errorMessage\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(" "),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("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 keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),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("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" returndata"),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 comment"}},[t._v("// Look for revert reason and bubble it up if present")]),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("returndata"),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 comment"}},[t._v("// The easiest way to bubble the revert reason is using memory via assembly")]),t._v("\n\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("let")]),t._v(" returndata_size "),s("span",{pre:!0,attrs:{class:"token operator"}},[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("returndata"),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(" returndata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" returndata_size"),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("revert")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("errorMessage"),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("\n")])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/49.5425ea98.js b/.vuepress/dist/assets/js/49.fe0613a1.js similarity index 99% rename from .vuepress/dist/assets/js/49.5425ea98.js rename to .vuepress/dist/assets/js/49.fe0613a1.js index 535857e..256d10c 100644 --- a/.vuepress/dist/assets/js/49.5425ea98.js +++ b/.vuepress/dist/assets/js/49.fe0613a1.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[49],{369:function(t,s,a){"use strict";a.r(s);var e=a(17),r=Object(e.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-5"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#實例解析-proof-of-stake-書籍的捐款合約-part-5"}},[t._v("#")]),t._v(" 實例解析 - Proof of Stake 書籍的捐款合約 Part 5")]),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\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(" "),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"),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(" IERC165"),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(" IERC721Receiver"),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(" IERC721Metadata"),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("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(" ERC165"),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("前文"),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"),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"),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(" IERC165"),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("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:"ierc721-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#ierc721-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("IERC721.sol")])]),t._v(" "),s("p",[t._v("請參考"),s("a",{attrs:{href:"https://ithelp.ithome.com.tw/articles/10301718",target:"_blank",rel:"noopener noreferrer"}},[t._v("前文「ERC721 非同值性代幣(NFT)標準」"),s("OutboundLink")],1),t._v("。")]),t._v(" "),s("h3",{attrs:{id:"ierc721enumerable-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#ierc721enumerable-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("IERC721Enumerable.sol")])]),t._v(" "),s("p",[t._v("請參考"),s("a",{attrs:{href:"https://ithelp.ithome.com.tw/articles/10303007",target:"_blank",rel:"noopener noreferrer"}},[t._v("前文「ERC721 的列舉擴充(enumeration extension)」"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"ierc721metadata-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#ierc721metadata-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("IERC721Metadata.sol")])]),t._v(" "),s("p",[t._v("請參考"),s("a",{attrs:{href:"https://ithelp.ithome.com.tw/articles/10302264",target:"_blank",rel:"noopener noreferrer"}},[t._v("前文「ERC721 的元資料擴充(metadata extension)」"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"ierc721receiver-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#ierc721receiver-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("IERC721Receiver.sol")])]),t._v(" "),s("p",[s("code",[t._v("IERC721Receiver")]),t._v(" 是一個 ERC721 的附屬介面,用來檢查該合約是否支援 ERC721 標準中的「"),s("code",[t._v("safeTransfers")]),t._v("」的操作。")]),t._v(" "),s("p",[t._v("當 "),s("code",[t._v("safeTransfers")]),t._v(" 被呼叫時,在轉移後必定會呼叫這個介面中的函式「"),s("code",[t._v("onERC721Received")]),t._v("」,而欲支援 ERC721 的安全轉移的合約必須實作這個函式且回傳該函式的 "),s("code",[t._v("Solidity selector")]),t._v("(透過 "),s("code",[t._v("IERC721.onERC721Received.selector")]),t._v(" 取得)。其他任何與此數值不同的回傳值,將觸發 "),s("code",[t._v("revert")]),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 * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IERC721Receiver")]),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("/**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\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("onERC721Received")]),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(" operator"),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("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("calldata")]),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("external")]),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")]),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:"ierc165-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#ierc165-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("IERC165.sol")])]),t._v(" "),s("p",[s("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-165",target:"_blank",rel:"noopener noreferrer"}},[t._v("EIP-165"),s("OutboundLink")],1),t._v(" 用來偵測該合約實作了哪些標準介面。")]),t._v(" "),s("p",[t._v("由於合約的標準很多元,因此一個合約中可能支援不只一種標準,為了能精準地得知該合約有哪些可能的操作介面,因此 ERC165 是非常重要的標準,用來讓其他人知道怎麼正確地與合約進行互動。")]),t._v(" "),s("p",[t._v("實作此標準的開發者應正確地使用 "),s("code",[t._v("supportsInterface")]),t._v(",應在裡面判斷 "),s("code",[t._v("interfaceId")]),t._v(" 是否與 "),s("code",[t._v("type(Interface).interfaceId")]),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 Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IERC165")]),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("/**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\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("external")]),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("bool")]),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")])])])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[49],{373:function(t,s,a){"use strict";a.r(s);var e=a(17),r=Object(e.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-5"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#實例解析-proof-of-stake-書籍的捐款合約-part-5"}},[t._v("#")]),t._v(" 實例解析 - Proof of Stake 書籍的捐款合約 Part 5")]),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\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(" "),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"),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(" IERC165"),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(" IERC721Receiver"),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(" IERC721Metadata"),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("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(" ERC165"),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("前文"),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"),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"),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(" IERC165"),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("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:"ierc721-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#ierc721-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("IERC721.sol")])]),t._v(" "),s("p",[t._v("請參考"),s("a",{attrs:{href:"https://ithelp.ithome.com.tw/articles/10301718",target:"_blank",rel:"noopener noreferrer"}},[t._v("前文「ERC721 非同值性代幣(NFT)標準」"),s("OutboundLink")],1),t._v("。")]),t._v(" "),s("h3",{attrs:{id:"ierc721enumerable-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#ierc721enumerable-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("IERC721Enumerable.sol")])]),t._v(" "),s("p",[t._v("請參考"),s("a",{attrs:{href:"https://ithelp.ithome.com.tw/articles/10303007",target:"_blank",rel:"noopener noreferrer"}},[t._v("前文「ERC721 的列舉擴充(enumeration extension)」"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"ierc721metadata-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#ierc721metadata-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("IERC721Metadata.sol")])]),t._v(" "),s("p",[t._v("請參考"),s("a",{attrs:{href:"https://ithelp.ithome.com.tw/articles/10302264",target:"_blank",rel:"noopener noreferrer"}},[t._v("前文「ERC721 的元資料擴充(metadata extension)」"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"ierc721receiver-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#ierc721receiver-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("IERC721Receiver.sol")])]),t._v(" "),s("p",[s("code",[t._v("IERC721Receiver")]),t._v(" 是一個 ERC721 的附屬介面,用來檢查該合約是否支援 ERC721 標準中的「"),s("code",[t._v("safeTransfers")]),t._v("」的操作。")]),t._v(" "),s("p",[t._v("當 "),s("code",[t._v("safeTransfers")]),t._v(" 被呼叫時,在轉移後必定會呼叫這個介面中的函式「"),s("code",[t._v("onERC721Received")]),t._v("」,而欲支援 ERC721 的安全轉移的合約必須實作這個函式且回傳該函式的 "),s("code",[t._v("Solidity selector")]),t._v("(透過 "),s("code",[t._v("IERC721.onERC721Received.selector")]),t._v(" 取得)。其他任何與此數值不同的回傳值,將觸發 "),s("code",[t._v("revert")]),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 * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IERC721Receiver")]),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("/**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\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("onERC721Received")]),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(" operator"),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("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("calldata")]),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("external")]),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")]),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:"ierc165-sol"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#ierc165-sol"}},[t._v("#")]),t._v(" "),s("code",[t._v("IERC165.sol")])]),t._v(" "),s("p",[s("a",{attrs:{href:"https://eips.ethereum.org/EIPS/eip-165",target:"_blank",rel:"noopener noreferrer"}},[t._v("EIP-165"),s("OutboundLink")],1),t._v(" 用來偵測該合約實作了哪些標準介面。")]),t._v(" "),s("p",[t._v("由於合約的標準很多元,因此一個合約中可能支援不只一種標準,為了能精準地得知該合約有哪些可能的操作介面,因此 ERC165 是非常重要的標準,用來讓其他人知道怎麼正確地與合約進行互動。")]),t._v(" "),s("p",[t._v("實作此標準的開發者應正確地使用 "),s("code",[t._v("supportsInterface")]),t._v(",應在裡面判斷 "),s("code",[t._v("interfaceId")]),t._v(" 是否與 "),s("code",[t._v("type(Interface).interfaceId")]),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 Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IERC165")]),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("/**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\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("external")]),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("bool")]),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")])])])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/51.c0c6d69d.js b/.vuepress/dist/assets/js/51.d6749299.js similarity index 99% rename from .vuepress/dist/assets/js/51.c0c6d69d.js rename to .vuepress/dist/assets/js/51.d6749299.js index 796dc19..f997d26 100644 --- a/.vuepress/dist/assets/js/51.c0c6d69d.js +++ b/.vuepress/dist/assets/js/51.d6749299.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[51],{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-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/.vuepress/dist/assets/js/52.2ca06770.js b/.vuepress/dist/assets/js/52.a91199e7.js similarity index 98% rename from .vuepress/dist/assets/js/52.2ca06770.js rename to .vuepress/dist/assets/js/52.a91199e7.js index fd30b4a..00a0e20 100644 --- a/.vuepress/dist/assets/js/52.2ca06770.js +++ b/.vuepress/dist/assets/js/52.a91199e7.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[52],{370: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],{376: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/.vuepress/dist/assets/js/53.27e1c49e.js b/.vuepress/dist/assets/js/53.c312c13b.js similarity index 89% rename from .vuepress/dist/assets/js/53.27e1c49e.js rename to .vuepress/dist/assets/js/53.c312c13b.js index 2aeea5f..0365cfd 100644 --- a/.vuepress/dist/assets/js/53.27e1c49e.js +++ b/.vuepress/dist/assets/js/53.c312c13b.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[53],{372: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],{371: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/.vuepress/dist/assets/js/54.978645b9.js b/.vuepress/dist/assets/js/54.1d257938.js similarity index 98% rename from .vuepress/dist/assets/js/54.978645b9.js rename to .vuepress/dist/assets/js/54.1d257938.js index 3a1307b..23b4b74 100644 --- a/.vuepress/dist/assets/js/54.978645b9.js +++ b/.vuepress/dist/assets/js/54.1d257938.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[54],{371:function(t,i,a){"use strict";a.r(i);var n=a(17),v=Object(n.a)({},(function(){var t=this,i=t._self._c;return i("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[i("h1",{attrs:{id:"前言"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#前言"}},[t._v("#")]),t._v(" 前言")]),t._v(" "),i("p",[t._v("或許各位同學已經看過我之前為了參加鐵人賽所錄製的「淺入淺出 EVM Object Format」的影片系列,由於當初錄製的時候時程較趕,因此有些內容與背景知識並沒有講得很清楚,有不少同學跟我反應沒有基礎概念很難聽懂與跟上進度,更覺得 EOF 玄之又玄難以理解。")]),t._v(" "),i("p",[t._v("因此我打算重新錄製新的「深入淺出 EOF」系列,除了原本介紹 EOFv1 相關的 EIPs 以外,盡可能加入更多的基礎知識,希望能夠讓大家更加了解 EVM Object Format。")]),t._v(" "),i("h2",{attrs:{id:"關於-eof"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#關於-eof"}},[t._v("#")]),t._v(" 關於 EOF")]),t._v(" "),i("p",[t._v("EVM Object format 的第一個版本其實積累了多年來許多針對以太坊虛擬機(EVM)的改善與增強,由於近年來以太坊的發展重心並不在 EVM 本身,更多的是在共識機制、隱私保護、可擴展性等議題,如:PoS、zk-SNARKs、sharding 等等,因此 EVM Object Format 的相關提案雖然已經發展很長的時間了,但一直都沒能進到硬分叉的階段。")]),t._v(" "),i("p",[t._v("終於在這次的 Pectra 升級中被加入到以太坊主網中,這對於智慧合約開發的發展來說毫無疑問地是個重要的里程碑,不只會改變現在的智慧合約的底層架構,也對靜態分析等相關工具有很大的影響。巧婦難為無米之炊,以前是 EVM 不夠好限制很多,做事情綁手綁腳的,但現在有了 EOF 的出現將為以太坊的智慧合約開發帶來更多的可能性。")]),t._v(" "),i("h2",{attrs:{id:"大綱"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#大綱"}},[t._v("#")]),t._v(" 大綱")]),t._v(" "),i("p",[t._v("這次的系列將會分為以下幾個章節:")]),t._v(" "),i("ol",[i("li",[t._v("前言")]),t._v(" "),i("li",[t._v("以太坊虛擬機簡介\n"),i("ol",[i("li",[t._v("什麼是以太坊虛擬機 (Ethereum Virtual Machine, EVM)")]),t._v(" "),i("li",[t._v("什麼是以太坊虛擬機組合語言 (Ethereum Virtual Machine Assembly Language, EVM Assembly Language)")]),t._v(" "),i("li",[t._v("什麼是以太坊虛擬機位元組碼 (Ethereum Virtual Machine Bytecode, EVM Bytecode)")])])]),t._v(" "),i("li",[t._v("智慧合約簡介\n"),i("ol",[i("li",[t._v("什麼是智慧合約 (Smart Contract)")]),t._v(" "),i("li",[t._v("如何撰寫一份智慧合約,以 Solidity 為例")]),t._v(" "),i("li",[t._v("如何將智慧合約編譯成以太坊虛擬機位元組碼")]),t._v(" "),i("li",[t._v("如何將智慧合約部署到以太坊主網 (Mainnet)")]),t._v(" "),i("li",[t._v("如何與智慧合約互動")])])]),t._v(" "),i("li",[t._v("什麼是以太坊物件格式 (EVM Object Format, EOF)\n"),i("ol",[i("li",[t._v("EIP-7692: EVM Object Format (EOF) v1 Meta")]),t._v(" "),i("li",[t._v("EIP-3541: Reject new contract code starting with the 0xEF byte")]),t._v(" "),i("li",[t._v("EIP-3540: EOFv1")]),t._v(" "),i("li",[t._v("現在的合約是怎麼驗證的")]),t._v(" "),i("li",[t._v("EIP-3670: EOF - Code Validation - Validate EOF bytecode for correctness at the time of deployment")]),t._v(" "),i("li",[t._v("現在的合約是怎麼處理 JUMP 的")]),t._v(" "),i("li",[t._v("EIP-4200: EOF - Static relative jumps - RJUMP, RJUMPI and RJUMPV instructions with a signed immediate encoding the jump destination")]),t._v(" "),i("li",[t._v("現在的合約是如何存取 Data 的")]),t._v(" "),i("li",[t._v("EIP-7480: EOF - Data section access instructions")]),t._v(" "),i("li",[t._v("現在的合約是如何處理 Stack 的")]),t._v(" "),i("li",[t._v("EIP-663: SWAPN, DUPN and EXCHANGE instructions")]),t._v(" "),i("li",[t._v("現在的合約是如何處理 CALL 的")]),t._v(" "),i("li",[t._v("EIP-7069: Revamped CALL instructions - Introduce EXTCALL, EXTDELEGATECALL and EXTSTATICCALL with simplified semantics")]),t._v(" "),i("li",[t._v("EIP-4750: EOF - Functions - Individual sections for functions with "),i("code",[t._v("CALLF")]),t._v(" and "),i("code",[t._v("RETF")]),t._v(" instructions")]),t._v(" "),i("li",[t._v("EIP-6206: EOF - JUMPF and non-returning functions - Introduces instruction for chaining function calls")]),t._v(" "),i("li",[t._v("現在的合約是怎麼處理部署新合約的")]),t._v(" "),i("li",[t._v("EIP-7620: EOF Contract Creation - Introduce "),i("code",[t._v("EOFCREATE")]),t._v(" and "),i("code",[t._v("RETURNCONTRACT")]),t._v(" instructions")]),t._v(" "),i("li",[t._v("EIP-7698: EOF - Creation transaction - Deploy EOF contracts using creation transactions")]),t._v(" "),i("li",[t._v("EIP-5450: EOF - Stack Validation - Deploy-time validation of stack usage for EOF functions")])])]),t._v(" "),i("li",[t._v("總結")])])])}),[],!1,null,null,null);i.default=v.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[54],{374:function(t,i,a){"use strict";a.r(i);var n=a(17),v=Object(n.a)({},(function(){var t=this,i=t._self._c;return i("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[i("h1",{attrs:{id:"前言"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#前言"}},[t._v("#")]),t._v(" 前言")]),t._v(" "),i("p",[t._v("或許各位同學已經看過我之前為了參加鐵人賽所錄製的「淺入淺出 EVM Object Format」的影片系列,由於當初錄製的時候時程較趕,因此有些內容與背景知識並沒有講得很清楚,有不少同學跟我反應沒有基礎概念很難聽懂與跟上進度,更覺得 EOF 玄之又玄難以理解。")]),t._v(" "),i("p",[t._v("因此我打算重新錄製新的「深入淺出 EOF」系列,除了原本介紹 EOFv1 相關的 EIPs 以外,盡可能加入更多的基礎知識,希望能夠讓大家更加了解 EVM Object Format。")]),t._v(" "),i("h2",{attrs:{id:"關於-eof"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#關於-eof"}},[t._v("#")]),t._v(" 關於 EOF")]),t._v(" "),i("p",[t._v("EVM Object format 的第一個版本其實積累了多年來許多針對以太坊虛擬機(EVM)的改善與增強,由於近年來以太坊的發展重心並不在 EVM 本身,更多的是在共識機制、隱私保護、可擴展性等議題,如:PoS、zk-SNARKs、sharding 等等,因此 EVM Object Format 的相關提案雖然已經發展很長的時間了,但一直都沒能進到硬分叉的階段。")]),t._v(" "),i("p",[t._v("終於在這次的 Pectra 升級中被加入到以太坊主網中,這對於智慧合約開發的發展來說毫無疑問地是個重要的里程碑,不只會改變現在的智慧合約的底層架構,也對靜態分析等相關工具有很大的影響。巧婦難為無米之炊,以前是 EVM 不夠好限制很多,做事情綁手綁腳的,但現在有了 EOF 的出現將為以太坊的智慧合約開發帶來更多的可能性。")]),t._v(" "),i("h2",{attrs:{id:"大綱"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#大綱"}},[t._v("#")]),t._v(" 大綱")]),t._v(" "),i("p",[t._v("這次的系列將會分為以下幾個章節:")]),t._v(" "),i("ol",[i("li",[t._v("前言")]),t._v(" "),i("li",[t._v("以太坊虛擬機簡介\n"),i("ol",[i("li",[t._v("什麼是以太坊虛擬機 (Ethereum Virtual Machine, EVM)")]),t._v(" "),i("li",[t._v("什麼是以太坊虛擬機組合語言 (Ethereum Virtual Machine Assembly Language, EVM Assembly Language)")]),t._v(" "),i("li",[t._v("什麼是以太坊虛擬機位元組碼 (Ethereum Virtual Machine Bytecode, EVM Bytecode)")])])]),t._v(" "),i("li",[t._v("智慧合約簡介\n"),i("ol",[i("li",[t._v("什麼是智慧合約 (Smart Contract)")]),t._v(" "),i("li",[t._v("如何撰寫一份智慧合約,以 Solidity 為例")]),t._v(" "),i("li",[t._v("如何將智慧合約編譯成以太坊虛擬機位元組碼")]),t._v(" "),i("li",[t._v("如何將智慧合約部署到以太坊主網 (Mainnet)")]),t._v(" "),i("li",[t._v("如何與智慧合約互動")])])]),t._v(" "),i("li",[t._v("什麼是以太坊物件格式 (EVM Object Format, EOF)\n"),i("ol",[i("li",[t._v("EIP-7692: EVM Object Format (EOF) v1 Meta")]),t._v(" "),i("li",[t._v("EIP-3541: Reject new contract code starting with the 0xEF byte")]),t._v(" "),i("li",[t._v("EIP-3540: EOFv1")]),t._v(" "),i("li",[t._v("現在的合約是怎麼驗證的")]),t._v(" "),i("li",[t._v("EIP-3670: EOF - Code Validation - Validate EOF bytecode for correctness at the time of deployment")]),t._v(" "),i("li",[t._v("現在的合約是怎麼處理 JUMP 的")]),t._v(" "),i("li",[t._v("EIP-4200: EOF - Static relative jumps - RJUMP, RJUMPI and RJUMPV instructions with a signed immediate encoding the jump destination")]),t._v(" "),i("li",[t._v("現在的合約是如何存取 Data 的")]),t._v(" "),i("li",[t._v("EIP-7480: EOF - Data section access instructions")]),t._v(" "),i("li",[t._v("現在的合約是如何處理 Stack 的")]),t._v(" "),i("li",[t._v("EIP-663: SWAPN, DUPN and EXCHANGE instructions")]),t._v(" "),i("li",[t._v("現在的合約是如何處理 CALL 的")]),t._v(" "),i("li",[t._v("EIP-7069: Revamped CALL instructions - Introduce EXTCALL, EXTDELEGATECALL and EXTSTATICCALL with simplified semantics")]),t._v(" "),i("li",[t._v("EIP-4750: EOF - Functions - Individual sections for functions with "),i("code",[t._v("CALLF")]),t._v(" and "),i("code",[t._v("RETF")]),t._v(" instructions")]),t._v(" "),i("li",[t._v("EIP-6206: EOF - JUMPF and non-returning functions - Introduces instruction for chaining function calls")]),t._v(" "),i("li",[t._v("現在的合約是怎麼處理部署新合約的")]),t._v(" "),i("li",[t._v("EIP-7620: EOF Contract Creation - Introduce "),i("code",[t._v("EOFCREATE")]),t._v(" and "),i("code",[t._v("RETURNCONTRACT")]),t._v(" instructions")]),t._v(" "),i("li",[t._v("EIP-7698: EOF - Creation transaction - Deploy EOF contracts using creation transactions")]),t._v(" "),i("li",[t._v("EIP-5450: EOF - Stack Validation - Deploy-time validation of stack usage for EOF functions")])])]),t._v(" "),i("li",[t._v("總結")])])])}),[],!1,null,null,null);i.default=v.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/55.6f4fc799.js b/.vuepress/dist/assets/js/55.6f4fc799.js new file mode 100644 index 0000000..e8111a2 --- /dev/null +++ b/.vuepress/dist/assets/js/55.6f4fc799.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[55],{369:function(t,s,e){"use strict";e.r(s);var r=e(17),a=Object(r.a)({},(function(){var t=this._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[t("h1",{attrs:{id:"深入淺出-eofv1"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#深入淺出-eofv1"}},[this._v("#")]),this._v(" 深入淺出 EOFv1")]),this._v(" "),t("p",[this._v("為一系列以 EVM Object Format 為主題的教學課程,包含影片與文章,為「淺入淺出 EOF」的重製版本。將以完全初學者的角度入手,從各種背景知識開始介紹,由淺入深的讓讀者對 EOF 能有更完整的印象。")])])}),[],!1,null,null,null);s.default=a.exports}}]); \ No newline at end of file diff --git a/.vuepress/dist/assets/js/app.63a1f9a8.js b/.vuepress/dist/assets/js/app.24badece.js similarity index 74% rename from .vuepress/dist/assets/js/app.63a1f9a8.js rename to .vuepress/dist/assets/js/app.24badece.js index 94490ff..3c8dd6a 100644 --- a/.vuepress/dist/assets/js/app.63a1f9a8.js +++ b/.vuepress/dist/assets/js/app.24badece.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/.vuepress/dist/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/.vuepress/dist/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 4e1ed92..9614137 100644 --- "a/.vuepress/dist/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/.vuepress/dist/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 @@ - + @@ -45,6 +45,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/03-\344\273\200\351\272\274\346\230\257\344\272\244\346\230\223.html" "b/.vuepress/dist/ethereum-101/03-\344\273\200\351\272\274\346\230\257\344\272\244\346\230\223.html" index ba3e385..3461beb 100644 --- "a/.vuepress/dist/ethereum-101/03-\344\273\200\351\272\274\346\230\257\344\272\244\346\230\223.html" +++ "b/.vuepress/dist/ethereum-101/03-\344\273\200\351\272\274\346\230\257\344\272\244\346\230\223.html" @@ -8,7 +8,7 @@ - + @@ -50,6 +50,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/04-\347\207\203\346\226\231\350\210\207\346\211\213\347\272\214\350\262\273.html" "b/.vuepress/dist/ethereum-101/04-\347\207\203\346\226\231\350\210\207\346\211\213\347\272\214\350\262\273.html" index a2f3179..eeb1e58 100644 --- "a/.vuepress/dist/ethereum-101/04-\347\207\203\346\226\231\350\210\207\346\211\213\347\272\214\350\262\273.html" +++ "b/.vuepress/dist/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 @@ - + @@ -43,6 +43,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/05-\345\270\263\346\210\266.html" "b/.vuepress/dist/ethereum-101/05-\345\270\263\346\210\266.html" index a34266f..b12bb2b 100644 --- "a/.vuepress/dist/ethereum-101/05-\345\270\263\346\210\266.html" +++ "b/.vuepress/dist/ethereum-101/05-\345\270\263\346\210\266.html" @@ -8,7 +8,7 @@ - + @@ -42,6 +42,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/06-\347\266\262\350\267\257.html" "b/.vuepress/dist/ethereum-101/06-\347\266\262\350\267\257.html" index 627b021..1f70800 100644 --- "a/.vuepress/dist/ethereum-101/06-\347\266\262\350\267\257.html" +++ "b/.vuepress/dist/ethereum-101/06-\347\266\262\350\267\257.html" @@ -8,7 +8,7 @@ - + @@ -42,6 +42,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/07-\345\205\261\350\255\230\346\251\237\345\210\266.html" "b/.vuepress/dist/ethereum-101/07-\345\205\261\350\255\230\346\251\237\345\210\266.html" index bdcac77..31a8d44 100644 --- "a/.vuepress/dist/ethereum-101/07-\345\205\261\350\255\230\346\251\237\345\210\266.html" +++ "b/.vuepress/dist/ethereum-101/07-\345\205\261\350\255\230\346\251\237\345\210\266.html" @@ -8,7 +8,7 @@ - + @@ -42,6 +42,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/08-\345\267\245\344\275\234\351\207\217\350\255\211\346\230\216.html" "b/.vuepress/dist/ethereum-101/08-\345\267\245\344\275\234\351\207\217\350\255\211\346\230\216.html" index cab8d38..84f1201 100644 --- "a/.vuepress/dist/ethereum-101/08-\345\267\245\344\275\234\351\207\217\350\255\211\346\230\216.html" +++ "b/.vuepress/dist/ethereum-101/08-\345\267\245\344\275\234\351\207\217\350\255\211\346\230\216.html" @@ -8,7 +8,7 @@ - + @@ -44,6 +44,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/09-\346\254\212\347\233\212\350\255\211\346\230\216.html" "b/.vuepress/dist/ethereum-101/09-\346\254\212\347\233\212\350\255\211\346\230\216.html" index f69a730..b8bd98c 100644 --- "a/.vuepress/dist/ethereum-101/09-\346\254\212\347\233\212\350\255\211\346\230\216.html" +++ "b/.vuepress/dist/ethereum-101/09-\346\254\212\347\233\212\350\255\211\346\230\216.html" @@ -8,7 +8,7 @@ - + @@ -41,6 +41,6 @@ →

- + diff --git "a/.vuepress/dist/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/.vuepress/dist/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 6a03fae..3dc051f 100644 --- "a/.vuepress/dist/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/.vuepress/dist/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 @@ - + @@ -41,6 +41,6 @@ →

- + diff --git "a/.vuepress/dist/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/.vuepress/dist/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 e33f71e..176271f 100644 --- "a/.vuepress/dist/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/.vuepress/dist/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 @@ - + @@ -55,6 +55,6 @@ →

- + diff --git "a/.vuepress/dist/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/.vuepress/dist/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 71d93c3..62fd7c8 100644 --- "a/.vuepress/dist/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/.vuepress/dist/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 @@ - + @@ -42,6 +42,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/13-ERC20\344\273\243\345\271\243\346\250\231\346\272\226.html" "b/.vuepress/dist/ethereum-101/13-ERC20\344\273\243\345\271\243\346\250\231\346\272\226.html" index 4eef02f..515b1b8 100644 --- "a/.vuepress/dist/ethereum-101/13-ERC20\344\273\243\345\271\243\346\250\231\346\272\226.html" +++ "b/.vuepress/dist/ethereum-101/13-ERC20\344\273\243\345\271\243\346\250\231\346\272\226.html" @@ -8,7 +8,7 @@ - + @@ -67,6 +67,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/14-ERC20\344\276\213\345\255\220.html" "b/.vuepress/dist/ethereum-101/14-ERC20\344\276\213\345\255\220.html" index 092c00e..02d450f 100644 --- "a/.vuepress/dist/ethereum-101/14-ERC20\344\276\213\345\255\220.html" +++ "b/.vuepress/dist/ethereum-101/14-ERC20\344\276\213\345\255\220.html" @@ -8,7 +8,7 @@ - + @@ -41,6 +41,6 @@ →

- + diff --git "a/.vuepress/dist/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/.vuepress/dist/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 33867bc..5e2be1c 100644 --- "a/.vuepress/dist/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/.vuepress/dist/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 @@ - + @@ -88,6 +88,6 @@ →

- + diff --git "a/.vuepress/dist/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/.vuepress/dist/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 afd0586..34cd092 100644 --- "a/.vuepress/dist/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/.vuepress/dist/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 @@ - + @@ -81,6 +81,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/17-ERC721\347\232\204\345\210\227\350\210\211\346\223\264\345\205\205.html" "b/.vuepress/dist/ethereum-101/17-ERC721\347\232\204\345\210\227\350\210\211\346\223\264\345\205\205.html" index e9fd266..f35cd6e 100644 --- "a/.vuepress/dist/ethereum-101/17-ERC721\347\232\204\345\210\227\350\210\211\346\223\264\345\205\205.html" +++ "b/.vuepress/dist/ethereum-101/17-ERC721\347\232\204\345\210\227\350\210\211\346\223\264\345\205\205.html" @@ -8,7 +8,7 @@ - + @@ -65,6 +65,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/18-ERC721A\347\232\204\346\224\271\351\200\262.html" "b/.vuepress/dist/ethereum-101/18-ERC721A\347\232\204\346\224\271\351\200\262.html" index ccee53a..d70555c 100644 --- "a/.vuepress/dist/ethereum-101/18-ERC721A\347\232\204\346\224\271\351\200\262.html" +++ "b/.vuepress/dist/ethereum-101/18-ERC721A\347\232\204\346\224\271\351\200\262.html" @@ -8,7 +8,7 @@ - + @@ -47,6 +47,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/19-ERC721R-\346\234\211\351\221\221\350\263\236\346\234\237\347\232\204NFT.html" "b/.vuepress/dist/ethereum-101/19-ERC721R-\346\234\211\351\221\221\350\263\236\346\234\237\347\232\204NFT.html" index 46ebf94..fba40f8 100644 --- "a/.vuepress/dist/ethereum-101/19-ERC721R-\346\234\211\351\221\221\350\263\236\346\234\237\347\232\204NFT.html" +++ "b/.vuepress/dist/ethereum-101/19-ERC721R-\346\234\211\351\221\221\350\263\236\346\234\237\347\232\204NFT.html" @@ -8,7 +8,7 @@ - + @@ -44,6 +44,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/20-ERC1155\345\244\232\345\205\203\344\273\243\345\271\243\346\250\231\346\272\226.html" "b/.vuepress/dist/ethereum-101/20-ERC1155\345\244\232\345\205\203\344\273\243\345\271\243\346\250\231\346\272\226.html" index cf6d803..7312bda 100644 --- "a/.vuepress/dist/ethereum-101/20-ERC1155\345\244\232\345\205\203\344\273\243\345\271\243\346\250\231\346\272\226.html" +++ "b/.vuepress/dist/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 @@ - + @@ -121,6 +121,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/21-ERC1155\347\232\204\346\241\210\344\276\213.html" "b/.vuepress/dist/ethereum-101/21-ERC1155\347\232\204\346\241\210\344\276\213.html" index 6240b23..432d5a4 100644 --- "a/.vuepress/dist/ethereum-101/21-ERC1155\347\232\204\346\241\210\344\276\213.html" +++ "b/.vuepress/dist/ethereum-101/21-ERC1155\347\232\204\346\241\210\344\276\213.html" @@ -8,7 +8,7 @@ - + @@ -44,6 +44,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/22-POAP\345\217\203\350\210\207\350\255\211\346\230\216.html" "b/.vuepress/dist/ethereum-101/22-POAP\345\217\203\350\210\207\350\255\211\346\230\216.html" index e53829f..9258362 100644 --- "a/.vuepress/dist/ethereum-101/22-POAP\345\217\203\350\210\207\350\255\211\346\230\216.html" +++ "b/.vuepress/dist/ethereum-101/22-POAP\345\217\203\350\210\207\350\255\211\346\230\216.html" @@ -8,7 +8,7 @@ - + @@ -42,6 +42,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/23-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" "b/.vuepress/dist/ethereum-101/23-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" index 278b351..f39da53 100644 --- "a/.vuepress/dist/ethereum-101/23-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" +++ "b/.vuepress/dist/ethereum-101/23-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" @@ -8,7 +8,7 @@ - + @@ -242,6 +242,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/24-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" "b/.vuepress/dist/ethereum-101/24-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" index 6f63349..2701984 100644 --- "a/.vuepress/dist/ethereum-101/24-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" +++ "b/.vuepress/dist/ethereum-101/24-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" @@ -8,7 +8,7 @@ - + @@ -193,6 +193,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/25-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" "b/.vuepress/dist/ethereum-101/25-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" index a3a7cc2..b02fdcd 100644 --- "a/.vuepress/dist/ethereum-101/25-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" +++ "b/.vuepress/dist/ethereum-101/25-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" @@ -8,7 +8,7 @@ - + @@ -195,6 +195,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/26-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" "b/.vuepress/dist/ethereum-101/26-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" index 1129573..c3b46da 100644 --- "a/.vuepress/dist/ethereum-101/26-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" +++ "b/.vuepress/dist/ethereum-101/26-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" @@ -8,7 +8,7 @@ - + @@ -278,6 +278,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/27-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" "b/.vuepress/dist/ethereum-101/27-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" index 10f37eb..cf05bd2 100644 --- "a/.vuepress/dist/ethereum-101/27-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" +++ "b/.vuepress/dist/ethereum-101/27-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" @@ -8,7 +8,7 @@ - + @@ -112,6 +112,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/28-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" "b/.vuepress/dist/ethereum-101/28-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" index 65e2ca1..718c087 100644 --- "a/.vuepress/dist/ethereum-101/28-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" +++ "b/.vuepress/dist/ethereum-101/28-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" @@ -8,7 +8,7 @@ - + @@ -761,6 +761,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/29-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" "b/.vuepress/dist/ethereum-101/29-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" index 4671d26..7a10234 100644 --- "a/.vuepress/dist/ethereum-101/29-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" +++ "b/.vuepress/dist/ethereum-101/29-\345\257\246\344\276\213\350\247\243\346\236\220Proof-of-Stake.html" @@ -8,7 +8,7 @@ - + @@ -600,6 +600,6 @@ →

- + diff --git "a/.vuepress/dist/ethereum-101/30-\347\265\220\350\252\236.html" "b/.vuepress/dist/ethereum-101/30-\347\265\220\350\252\236.html" index 36a60aa..94e72a7 100644 --- "a/.vuepress/dist/ethereum-101/30-\347\265\220\350\252\236.html" +++ "b/.vuepress/dist/ethereum-101/30-\347\265\220\350\252\236.html" @@ -8,7 +8,7 @@ - + @@ -38,6 +38,6 @@

- + diff --git a/.vuepress/dist/ethereum-101/index.html b/.vuepress/dist/ethereum-101/index.html index 1744c28..d3d9877 100644 --- a/.vuepress/dist/ethereum-101/index.html +++ b/.vuepress/dist/ethereum-101/index.html @@ -8,7 +8,7 @@ - + @@ -37,6 +37,6 @@ →

- + diff --git "a/.vuepress/dist/head-first-eof/01-\345\211\215\350\250\200.html" "b/.vuepress/dist/head-first-eof/01-\345\211\215\350\250\200.html" index c97e97d..8bca14f 100644 --- "a/.vuepress/dist/head-first-eof/01-\345\211\215\350\250\200.html" +++ "b/.vuepress/dist/head-first-eof/01-\345\211\215\350\250\200.html" @@ -8,7 +8,7 @@ - + @@ -32,10 +32,14 @@ 淺入淺出 EVM Object Format (opens new window) GitHub - (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. 以太坊虛擬機簡介 + (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/11/29 上午2:10:05
- +
  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
  • 總結
  • Last Updated: 2024/12/5 下午1:37:33
    + diff --git a/.vuepress/dist/head-first-eof/index.html b/.vuepress/dist/head-first-eof/index.html new file mode 100644 index 0000000..2a96647 --- /dev/null +++ b/.vuepress/dist/head-first-eof/index.html @@ -0,0 +1,42 @@ + + + + + + 深入淺出 EOFv1 | 一本關於 Ethereum 與 Solidity 智能合約的書 + + + + + + + + + + + + diff --git a/.vuepress/dist/index.html b/.vuepress/dist/index.html index 28ac984..0a91219 100644 --- a/.vuepress/dist/index.html +++ b/.vuepress/dist/index.html @@ -8,7 +8,7 @@ - + @@ -33,6 +33,6 @@ (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/11/29 上午2:10:05
    - + diff --git a/head-first-eof/README.md b/head-first-eof/README.md new file mode 100644 index 0000000..0648d2e --- /dev/null +++ b/head-first-eof/README.md @@ -0,0 +1,3 @@ +# 深入淺出 EOFv1 + +為一系列以 EVM Object Format 為主題的教學課程,包含影片與文章,為「淺入淺出 EOF」的重製版本。將以完全初學者的角度入手,從各種背景知識開始介紹,由淺入深的讓讀者對 EOF 能有更完整的印象。