無用 - 如何在 token 發行量裡埋彩蛋?
故事從一個名為 Cortex Coin 的幣說起。 它是由一個名為 Cortex 的項目發行的 ERC20 token。 因為他們沒有付我錢,所以我就不介紹這個項目在做什麼了。
Cortex Coin 有趣的一點是, 它的總發行量定為 299,792,458, 也就是光速的數值 (單位:m/s), 真是充滿工程師的浪漫!
我好奇他們為什麼選擇光速而不是其他常數, 就去讀了他們的白皮書。 在「7.2 Token Distribution」那段是這樣寫的:
In respect to the few natural constants of the physical universe, we choose the speed of light propagating in vacuum as total amount of token, 299792458.
其實也沒有解釋。
不過我們可以合理推斷他們選擇這個數值的原因: 目前主流的加密貨幣和token, 發行量大多在 1 million 到 1 trillion 之間, 原因之一是可以讓1枚貨幣的價格落在 0.01 到 100 美元附近, 這樣的價格不會低到讓人混淆(你能一眼看清楚 0.000001 USD 是多少嗎?), 也不會貴到讓人覺得連一顆都買不起。
要在 1 million 到 1 trillion 之間, 選出一個知名度最高的常數, 大概也只有光速的 299,792,458 了。 而且在不追求精確的情況下還可以簡單記成 300 million, 相當方便。
Constants
但我總覺得用光速不夠完美, 因為光速帶有單位 m/s ,只要換個單位,數值就不同了。 同理,幾乎所有物理常數都是帶有單位的,不夠純粹。
有沒有更純粹且有意義的數字可以用呢?
用數學中知名的常數如何?
π ≈ 3.14159
e ≈ 2.71828
可惜這些數字作為 token 發行量都太小了, 把它們乘以 1 million 或 1 billion 來用或許可以, 但有點牽強。
用跟程式有關的常數呢?
2^15 - 1 = 32,767 (16-bit int 的上限)
2^16 - 1 = 65,535 (16-bit unsigned int 的上限)
10^9 + 7 = 1,000,000,007 (一個小於 2^30 的質數,在程式競賽中常使用)
2^31 - 1 = 2,147,483,647 (32-bit int 的上限)
2^32 - 1 = 4,294,967,295 (32-bit unsigned int 的上限)
依照「在 1 million 到 1 trillion 之間」這個標準, 後三個都算可用, 用了也許能引起其他開發者的共鳴!
但還有一個小問題, ERC20 token 的數量通常允許帶有 18 位小數(這是普遍共識,不強迫遵循), 所以你看到的 2,147,483,647, 在區塊鏈上實際儲存的數值是 2,147,483,647,000,000,000,000,000,000 , 這個數字就不像 2,147,483,647 這麼有意義了。
那如果把「18位小數」也考慮進來, 能不能找到一個有意義且合適的數值呢?
(2^64 - 1) / (10^18) ≈ 18.447
(2^128 - 1) / (10^18) ≈ 3.4 * 10^20
前者太小,後者太大,都不合適。
引入了「18位小數」的概念後, 倒是讓某個數字似乎變得可以使用, 就是「Avogadro constant」(亞佛加厥常數)。
N_A ≈ 6.02214 * 10^23
這個數字的定義是「12克同位素碳-12所含的原子數量」, 就是「1莫耳」的數量。
雖然亞佛加厥常數也不是那麼純粹, 因為「克」是人類定義的, 但至少它是一個單純的數字。
用亞佛加厥常數的倍數來當發行量, 你就可以說你發行了「100 莫耳的 token」, 或你們打算募資「0.1 莫耳的 wei」(1 wei = 10^-18 ether) 之類的, 也許能吸引到化學系的人買你的 token!
Messages
除了去找本身有意義的常數來用, 另一種思路就是我們自己把訊息埋進數字裡。
例如我們可以將「時間」訊息埋進去。
Unix Time
在程式中, 時間通常用 Unix time 的形式來儲存, 它的定義是「從世界協調時間 1970年1月1日0時0分0秒 起至現在的總秒數」。 例如「2018年5月22日0時0分0秒」這個時刻會記錄成 1,526,947,200。 這個數值在 1 million 到 1 trillion 之間, 可以用!
如果你想讓發行量 = 合約部署時間, 可以這樣寫:
totalSupply_ = now * (10 ** uint256(decimals));
這樣大家就知道你的 token 是來鬧的了。
Date
用 Unix time 的缺點是, 一般人很難快速看出這個數字代表的意義, 所以我覺得更易懂的方法就是直接把日期寫出來。 例如: 20180522, 這個數字大約是 20 million, 可以用!
你可以用任何你覺得有意義的日期:
- 公司成立的日期
- ICO開始的日期
- 某人的生日
- 某個事件發生的日期
如果想讓你的 token 被中國禁止,就把總量設為 19890604 吧!
String
我們可以將任何資料轉換成 binary data, 而 binary data 可以轉換成數字, 所以可以用數字來儲存任何資料。
例如要用數字來儲存英文字串, 可以照這個流程:
English string -> ascii code (hex) -> decimal
(可將 ascii code 換成任意編碼)
例如:
“Roger” -> 0x526f676572 -> 354,056,365,426
(甚至不需要轉換成十進位,直接將 0x526f676572 寫進合約中也可以)
接下來要考慮的是, 用一個數字能儲存多長的字串?
Ethereum contract 的基本型別中, 數字最長是 256 bits, 一個字母的 ascii code 的長度是 8 bits 所以一個 256-bit 數字最多可以存 32 個字母。
但我們的 token 發行量不會用到 256 bits 這麼多。
假設發行量在 1 billion 左右,加上 18位小數, 總共是 10^27, 使用了 90 bits, 所以大概能存11~12個字母, 實在少得可憐。
Link
一個數字能存的訊息不多, 但我們也沒必要將所有訊息都放在數字裡, 可以把訊息放在其他地方, 再把連向那個訊息所需要的資訊放在數字裡即可。
例如使用任何 URL Shortener, 我們就可以將任何網址轉換成長度在6個字元左右的字串, 要存進一個 90 bits 的空間中是綽綽有餘。
舉另一個實用的例子, 每部 Youtube 影片都有一個唯一的 11 個字符長的 id, 由 a-z, A-Z, 0-9, -, _ 等 64 種符號組成, 例如「kJQP7kiw5Fk」。 將這個字串轉換成 ascii code 得到「0x6b4a5150376b697735466b」, 再轉換成十進位數字得到「129706017784974393382094443」, 除以 10^18 大約是「129,706,017」, 這個數字作為 token 發行量相當適合呢!
結語
- 說到底這篇就是個無用廢文啦,認真要發幣的話,還是用 100,000,000 這種簡單明瞭的數字吧。
- 真的要埋彩蛋的話,要注意不能寫成 Burnable Token 啊。
- 如果你想到了我沒想到的埋彩蛋的方法,歡迎留言告訴我!