Skip to main content

· 15 min read

Update: 11/30/2017 更新教程,使用Truffle 4.0.1

上一篇中介紹了智能合約📒 是什麼,也概略描述了從編譯到部署智能合約的流程,接下來將介紹如何使用 solidity 語言來寫智能合約。

使用 solidity 語言撰寫智能合約

Ethereum 上的智能合約需要使用solidity1語言來撰寫。雖然還有其他能用來撰寫智能合約的語言如Serpent(類 Python)、lll(類 Fortran),但目前看到所有公開的智能合約都是使用 solidity 撰寫。

宣傳上說,solidity 是一種類似 Javascript 的語言,而且圍繞著 solidity 的各種開發工具鏈,都是使用屬於 Javascript 生態系的 npm 來提供的。但我覺得 solidity 還是比較像 Java 或 C#。 因為和 Javascript 不同,solidity 與 Java 或 C# 同屬於強型別 (Strong Type,在定義變數時需要指定型別) 語言、在定義函式 (function) 時同樣需指定回傳的型別 (type)、同樣也需要先編譯才能執行。這些特性都是 Javascript 所不具備的。

開發前的準備

本文將使用當前最活躍的智能合約開發框架truffle3為基礎來開發。之前提到過的 ENS (Ethereum Name Service)5也是採用 truffle 框架。其他選擇還有embark4等。

就像一般網站或 App 開發一樣,在提供公開服務之前,開發者會在自己用於寫程式的電腦 (又稱作本機)💻 或透過測試網路🕸️ 來測試程式執行的效果,測試完成後,才會部署到公開的網路上提供服務。 開發區塊鏈智能合約 (程式) 的過程也是如此。特別是公開鏈上所有寫入或讀取計算結果的操作都需要真金白銀 (虛擬代幣)💸 ,而且根據網路狀況,每個公開鏈上的操作都需要要一小段反應時間 (15 秒~數分鐘),這些等待頗浪費寶貴的開發時間⏳ 。 因此在開發的過程中,我們將使用testrpc6工具在電腦上模擬智能合約所需的乙太坊區塊鏈測試環境。

testrpc 中也包含了 Javascript 版本的 Ethereum 虛擬機 (Ethereum Virtual Machine)7,因此可以完整地執行智能合約😇 。

此外,開發前還需準備一個合手的編輯器。我目前是使用Visual Studio Code搭配solidity插件來開發。solidity 插件除了支援語法高亮之外,也會透過 Solium11檢查並提示基本的語法錯誤,相當方便。其他編輯器應該也有類似的插件可選擇。

安裝所需工具

首先開發機上必須裝好 Node.js,再使用以下命令安裝所需的工具:

$ npm install -g ethereumjs-testrpc truffle

啟動 Testrpc

安裝好後隨時可以使用testrpc命令來啟動乙太坊測試環境。

$ testrpc
Available Accounts
==================
(0) 0xa4d7ce9137e6f8de4fb1311595b33230be15be50
(1) 0x26c231bdd7c8a7304983b04694c3437b30331019
(2) 0xe238ccca936dcdbd48f0cf3a1e6f147d04b55527
(3) 0x769ed341bf83cc86e5037cb78388012d6e2d9cc9
(4) 0x72a084c80195de79e5cd8dca59488e67982f65d7
(5) 0xcfda0765b0a82721d2f59581f53846a12e392999
(6) 0x4b0349aea768b4e1ed4cec683f8f7dd112729fea
(7) 0x643c305f0b3844984d7f1f7b9f3ab93a73dfdfcf
(8) 0x2ee0a7974326604442dca127d02fac4957ab3e8a
(9) 0xe00e57db1772f6e81bcccc982e565a10ae26ab92

Private Keys
==================
(0) 7de56fb677edc8d0c7a1f3a6d5bcb8f73ce257d44996e9b5fc8ad414af38a22a
(1) 4401de20cf287d15d1c062005d866a35cd82e2a73f8cb43ec0cb90b117d1ec38
(2) 8f51f9100a81218343d44a047ae3b0be5d80d262a13fbef24dc569b3e335e820
(3) 241a0ff98dfb6f290dbee909c9a7a4eea2de3a2174e7cddf834868ea03f80fa9
(4) ce1108cc6763bc74658068a55b080c6ccbfb1bd26e609588b81c07d13affc70d
(5) f9614c1fd34224787e6c95bbe881fb28fd0fdc00808ef85d0430505f4a348690
(6) 4c1baad08f720f5c5754bb185e66490b45e3480aa3ec419e4b76f7a81118b296
(7) af9af2c6b519d49605cc58b719240299e5e8b9a89a7e94a85625734fc30c46bd
(8) 55ab79ae6de4fad5b98bc1dfd795b945ba8e7d92dcc88073f9e3fdfef471f69f
(9) e9299fb391c8830370991659780933e6b62269e32a8cbc55a29aa5f73df995a2

HD Wallet
==================
Mnemonic: addict cherry medal cupboard bless reduce oven beauty egg gift pledge exact
Base HD Path: m/44'/60'/0'/0/{account_index}

可以看到 testrpc 啟動後自動建立了 10 個帳號 (Accounts),與每個帳號對應的私鑰 (Private Key)🔑 。每個帳號中都有 100 個測試用的以太幣 (Ether)💵 。要注意 testrpc 僅運行在記憶體中,因此每次重開時都會回到全新的狀態。

一切準備就緒,我們可以開始建立第一份智能合約專案了。

建立專案

開啟另一個命令列視窗,輸入以下命令以建立專案:

$ mkdir hello
$ cd hello
$ truffle init

如此一來,我們已建立好第一份智能合約專案了。

demo/資料夾下,可以看到contracts/資料夾,裡面放的是這個專案所包含的所有 solidity 程式。我們在contracts/資料夾中額外建立一個HelloWorld.sol檔案。(或者也可以用truffle create contract HelloWorld命令來建立)

HelloWorld.sol檔案內容如下:

pragma solidity ^0.4.11;

contract HelloWorld {
function sayHello() public returns (string) {
return ("Hello World");
}
}

講解

pragma solidity ^0.4.11;

第一行指名目前使用的 solidity 版本,不同版本的 solidity 可能會編譯出不同的 bytecode。

想要知道當前的 solidity 版本,也可以用 truffle version 命令來查看當前使用的 truffle 與 solidity 版本:

$ truffle version
Truffle v4.0.1 (core: 4.0.1)
Solidity v0.4.18 (solc-js)
contract HelloWorld {
...
}

contract關鍵字類似於其他語言中較常見的class。因為 solidity 是專為智能合約 (Contact) 設計的語言,宣告contract後即內建了開發智能合約所需的功能。也可以把這句理解為class HelloWorld extends Contract

雖然一個.sol 檔案中可以定義多個 Contract,但建議一個.sol 檔案中只定義一個 Contract 以便於後續的維護。

function sayHello() public returns (string) {
return ("Hello World");
}

函式的結構與其他程式類似,但如果有傳入的參數或回傳值,需要指定參數或回傳值的型別 (type)。所有支援的型別可以查看參考資料10

solidity 官方推薦的縮排風格為 4 個空格13

編譯

現在執行truffle compile命令,我們可以將HelloWorld.sol原始碼編譯成 Ethereum bytecode。

$ truffle compile

編譯成功的話,在build/contracts/目錄下會多出HelloWorld.json這個檔案。(在 Windows 平台上執行 truffle compile 若遇到問題,可以查看參考資料9來解決。)

部署

為了將寫好的 solidity 程式碼部署到區塊鍊上,我們需要做一些相應的設定。

遷移

truffle 框架中提供了方便部署合約的腳本。我們可以在migrations/目錄下維護這些腳本。這些腳本除了能部署合約,也可以用來遷移合約中的資料。建立migrations/2_deploy_contracts.js檔案 (這些腳本使用 Javascript 撰寫),將內容修改如下

var HelloWorld = artifacts.require("HelloWorld");

module.exports = function(deployer) {
deployer.deploy(HelloWorld);
};

這些 migration 檔案會依照檔案的編號來執行。例如2_就會在1_之後執行。檔案後面的文字只為協助開發者理解之用。

在檔案中可使用artifacts.require語句來取得準備部署的合約。使用deployer.deploy語句將合約部署到區塊鏈上。這邊HelloWorldcontract的名稱而不是檔名。因此可以用此語法讀入任一.sol檔案中的任一合約。

區塊網路設定

為了與testrpc連線,需要打開truffle.js並加入以下設定:

module.exports = {
// See <http://truffleframework.com/docs/advanced/configuration>
// to customize your Truffle configuration!
networks: {
development: {
host: "localhost",
port: 8545,
network_id: "*" // Match any network id
}
}
};

truffle 使用 Javascript 的 Object 格式來定義設定。這邊定義了development網路為localhost:8545,即 testrpc 所提供的網路位址。

部署

現在執行truffle migrate命令

$ truffle migrate
Using network 'development'.

Running migration: 1_initial_migration.js
...
Saving successful migration to network...
Running migration: 2_deploy_contracts.js
...
Saving successful migration to network...
...
Saving artifacts...

如此一來合約已經部署到 testrpc 中。切換到 testrpc 視窗,可以看到 testrpc 有反應了。

與合約互動

truffle 提供命令行工具,執行truffle console命令後,可用 Javascript 來和剛剛部署的合約互動。

$ truffle console
> let contract
> HelloWorld.deployed().then(instance => contract = instance)
> contract.sayHello.call()
'Hello World'
>

講解

> HelloWorld.deployed().then(instance => contract = instance)

truffle console中預載了truffle-contract12函式庫,以方便操作部署到區塊鏈上的合約。

這邊使用HelloWorld.deployed().then語句來取得 HelloWorld 合約的 Instance (實例),並存到contract變數中,以方便後續的呼叫。

上面用的是 Javascript ES6 + 的語法,這句也可以寫成

HelloWorld.deployed().then(function(instance) {
hello = instance;
});
> contract.sayHello.call()
'Hello World'

這邊直接呼叫contract.sayHello()也會得到一樣的結果。truffle-contract提供使用call()來讀取唯讀 (read only) 的資料,這樣就不需提供 gas。因此如果遇到的操作需要向區塊鏈寫入資料,我們就不能用call語句了。

如此一來,我們已寫好並部署完成了第一個智能合約,也驗證了合約確實可以運作。

加入新方法

我們在HelloWorld.sol中再加入一個echo方法,echo方法接受輸入一個參數,並回傳傳送的參數。

function echo(string name) constant returns (string) {
return name;
}

新的echo方法中傳入了一個name參數。我們也為echo方法加入一個constant宣告,表示呼叫這個方法並不會改變區塊鏈的狀態。如此一來,透過truffle-contract來呼叫此方法時,會自動選用call來呼叫,也不需要額外提供 gas。

由於更新了合約內容,我們需要先重新新編譯一次,將編譯結果部署到 testrpc 上,再透過truffle console執行看看結果。

$ truffle compile
...
$ truffle migrate --reset
...
$ truffle console
> let contract
> HelloWorld.deployed().then(instance => contract = instance)
> contract.echo("yo man")
'yo man'
>

echo方法確實將我們輸入的內容回傳了。同時因為宣告了constant,我們不需要直接呼叫call()方法,truffle會自動選用 call 來呼叫。

另一點需要注意的,是這次如果還是用truffle migrate命令,我們會得到如下訊息:

$ truffle migrate
Using network 'development'.

Network up to date.

Truffle 會告訴你現在網路上的合約都已是最新的,但事實上剛剛程式中新增的方法並沒有更新到區塊鏈上。要更新區塊鏈上已部署的程式,需要改寫migrations中的腳本,但現在還不到介紹 migration 的時候。還好我們開發用的區塊鏈是怎麼修改都沒關係的 testrpc,可以使用truffle migrate --reset命令直接重新在 testrpc 上部署一次🎉 。

使用 truffle develop 命令

truffle 4.0.0 版本之後加入了truffle develop命令。這個命令讓我們不需要另外安裝 testrpc 等環境,就能直接上手開發。

例如

truffle develop
Truffle Develop started at http://localhost:9545/

Accounts:
(0) 0x627306090abab3a6e1400e9345bc60c78a8bef57
(1) 0xf17f52151ebef6c7334fad080c5704d77216b732
(2) 0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef
(3) 0x821aea9a577a9b44299b9c15c88cf3087f3b5544
(4) 0x0d1d4e623d10f9fba5db95830f7d3839406c6af2
(5) 0x2932b7a2355d6fecc4b5c0b6bd44cc31df247a2e
(6) 0x2191ef87e392377ec08e7c08eb105ef5448eced5
(7) 0x0f4f2ac550a1b4e2280d04c21cea7ebd822934b5
(8) 0x6330a553fc93768f612722bb8c2ec78ac90b3bbc
(9) 0x5aeda56215b167893e80b4fe645ba6d5bab767de

Mnemonic: candy maple cake sugar pudding cream honey rich smooth crumble sweet treat

truffle(develop)> compile
truffle(develop)> migrate
Using network 'develop'.
Running migration: 1_initial_migration.js
Deploying Migrations...
...
Saving artifacts...
Running migration: 2_deploy_contracts.js
Deploying HelloWorld...
...
Saving artifacts...
truffle(develop)> let contract
truffle(develop)> HelloWorld.deployed().then(instance =>contract = instance)
...
truffle(develop)> contract.sayHello.call()
'Hello World'

可以看到,在命令行中輸入truffle develop命令,可以直接在裡面執行compilemigrate指令,還可以直接使用console命令所提供的與區塊鍊互動等功能。

結語

本篇設計的範例8相當簡單,但已達到完整地帶大家快速⚡ 走一遍智能合約開發流程的目的。要透過智能合約實現各種功能,可以參考Solidity by exampleTruffle getting started 網站學習更多的內容。也歡迎讀者留言,分享學習資源或提供建議。

下一篇會接著介紹如何建立一份簡單的加密代幣🔒💵合約。

參考資料

· 9 min read
聲明:gasolin.eth 此 Domain 已過期,我並未繼續註冊

智能合約是什麼?

在區塊鏈上運行的程式,通常稱為智能合約 (Smart Contract)📒 。所以通常會把 "寫區塊鏈程式" 改稱作 "寫智能合約"。雖然比特幣 (Bitcoin) 上也能寫智能合約,但是比特幣所支援的語法僅與交易有關,能做的事情比較有限。因此目前提到寫智能合約,通常指的是支援執行圖靈完備程式的以太坊 (Ethereum) 區塊鏈⛓️ 。

智能合約可以做什麼

目前最常見的智能合約是各種加密貨幣合約💷 ,開發者可以很容易地透過部署一個智能合約,來提供運行於以太坊上的新加密代幣。如果這份智能合約相容於 ERC20 標準1,開發者不需要重新開發從挖礦到交易的整個代幣生態系,你的新加密代幣就可以直接使用支援以太坊的電子錢包💰 來收送,大大降低了建立新加密代幣的門檻。

智能合約也讓募資💸 變得更透明。參與者投資資金或提供服務,也可獲得相應的權益。這份權益可以用代幣的形式返還給參與者。同樣地如果這代幣相容於 ERC20 標準2,投資者或贊助者還可以隨時交易這些代幣。讓資金的運用變得更加彈性,也降低了投資的門檻。

除此之外,智能合約也可以用來運作各式公開公正的自動服務機構 (DAO,Decentralized Autonomous Organization)🏦 。透過分散在全球各節點上運作的智能合約,所有運作與決策都是公開透明的,降低了交易的不確定性 (Uncertainty)。

智能合約和一般程式的差異

以太坊智能合約確實有些和一般程式不同的特性,以下整理了四個不同點。

一,整合金流容易

一般的應用程式要整合金流是件非常不容易的事情。而智能合約極容易整合金流系統 (使用以太幣或自行建立的新代幣合約)。

二,部署時與後續寫入時需費用

一般的應用程式需要提供網址讓使用者下載,一般的網頁應用程式也需要運行在伺服器上,開發者需要維持伺服器的運作以提供服務,這需要持續地花費(就算是免費的伺服器或網頁空間,也是廠商自行吸收了費用),程式開始運作後,除了維持費用外不需額外的花費。

智能合約在部署時需要一筆費用,這筆費用將分給參與交易驗證(挖礦)的人。而在合約部署成功後,合約會作為不可更改的區塊鏈的一部分,分散地儲存在全球各地以太坊的節點上。也因此,智能合約在部署後,並不需定期提供維持費用,同時查詢已寫入區塊鏈的靜態資料時也不需費用。只有在每次透過智能合約寫入或讀取計算結果時,需要提供一小筆交易費用。

三,儲存資料的成本更高

一般的應用程式將資料儲存在本機或伺服器上,需要資料時再從本機或伺服器上讀取,而智能合約將資料儲存在區塊鏈上,儲存資料所需的時間與成本相對昂貴。

四,部署後無法更改

一般的應用程式改版時可透過安裝新版程式,網頁應用程式也可透過部署新版程式達成,而智能合約一旦部署到區塊鏈上後,就無法更改這個智能合約。當然聰明的開發者透過加入額外的智能合約,也已有辦法繞過智能合約部署後無法再更改的限制。

如何撰寫智能合約?

Ethereum 上的智能合約需要使用 solidity2語言來撰寫。之前還有其他能用來撰寫智能合約的語言如 Serpent (類 Python)、lll (類 Fortran),但目前看到所有公開的智能合約都是使用 solidity 撰寫。官方宣傳上說 solidity 是一種類似 Javascript 的語言,而且圍繞著 solidity 的各種開發工具鏈都是使用屬於 Javascript 生態系的 npm 來提供的。

將智能合約部署到區塊鏈的流程

寫好 solidity 程式碼 (.sol) 後,需要先將程式碼編譯 (compile) 成 EVM (Ethereum Virtual Machine) 能讀懂的二進位 Contract ByteCode,才能部署到 Ethereum 的區塊鏈上執行。部署到區塊鏈上的合約會有一個和錢包地址(Address)一樣格式的合約地址(Contract Address)。

graph LR subgraph local .sol -- compile --> bytecode[Contract Bytecode] end subgraph ethereum bytecode -- deploy --> Contract end

部署後智能合約可自動執行。後續呼叫智能合約的時候,使用者可以使用部署合約的錢包地址 (Owner Account),或依據撰寫的智能合約條件,讓其他錢包地址也能呼叫這個智能合約。 所謂的 "呼叫智能合約",其實就是向這個合約地址發起交易,只是交易的不只是代幣,而可以是智能合約提供的呼叫方法。

graph LR subgraph local Account end subgraph ethereum Account -- call --> Contract Contract --> EVM end

有點抽象,來個例子? 🌰

收到我的 ENS 網域啦 gasolin.eth這篇文章中,我介紹了申請 Ethereum Name Service 的心得。其實 ENS 本身就是一堆智能合約的集合,透過這些智能合約,一起提供了 Ethereum Name Service 從申請,競價,到設定地址對應的服務。

要和智能合約互動,除了需要有合約地址外,還需要知道合約所提供的操作介面 (Application Binary Interface,ABI),即知道如何呼叫程式提供的功能,和如何解釋程式回傳的資料。 ABI(JSON 格式)檔案在從原始碼編譯成 ByteCode 時會一併產生。

下圖即是 ENS Public Resolver 這個合約的地址和 ABI。

準備好合約地址和 ABI 後,我們才能呼叫對應功能來存取合約。 Imgur

下一篇中,我將簡單介紹如何撰寫 Solidity 程式。

參考資料

· 5 min read

先記錄下來手邊使用的工具,才有機會從繁雜中歸納出簡單的使用規則。

20111年時紀錄了一次當時的個人工具箱,去年開始再次紀錄2。 今年給自己定的一大目標是個人自動化。年初開始紀錄自己工具箱的改變3🤹,持續更新。

主要裝備

  • 💻 Macbook Air 13", 2012 年版
  • 📱 One Plus 3, Android, 6GB RAM, 5.5" AMOLED
  • 💻 Dell XPS 13 (4943), Windows 10, i7 2.4GHz x2, 8GB RAM, 13" LCD
  • 📙 Kindle Voyage
  • 🖥️ Desktop PC, Elementary OS, Intel i7 3770 3.40GHz x8, 16GB RAM, GeForce GT 630, 23" LCD x2
  • 📦 Synology NAS: 電影,影集,照片,資料備份

和年初相比的改變:

主力用 Macbook Air,用回 Macbook Air 的主因,是因為目前工作中一定得用到的 mozreview 預期年底會淘汰,懶得為每台機器重新做設定。而且在 Windows 上編譯工作用的東西還是不太順手。 桌機多擺了一台螢幕,雙螢幕工作。

🕸️ 網站工具

和年初相比的改變:

使用多年的 Anobii 已經漸漸缺乏維護,嘗試使用Readmoo 分享書替代,但就我繁,簡,英文書交換著看的情況,Readmoo 分享書能掃到的書實在有限,因此今年到目前已看的書漏記了不少😓 。

此外也付費訂閱TodoistToshl兩種工具服務。

設計

開發

  • 編輯器:Visual Studio Code
  • 版本控制:git, git-cinnabar
  • 套件管理:apt, nvm, yarn, Chocolatey(windows)
  • Shell: zsh

Ubuntu bash on windows 用起來還不夠穩定,目前在 Windows 上盡量能用 Chocolatey 處理的就用 Chocolatey 處理。

常用插件

Browser

  • Emoji cheatsheet
  • A Weel translation
  • Context Plus
  • Grammarly (付費)

Grammarly 可以自動找出英文語法錯誤,相當方便。

VSCode

  • Git Blame
  • Document This
  • EditorConfig for VS Code
  • WakaTime
  • solidity

JS

  • Babel
  • ESlint

娛樂

  • 🎮Nintendo Switch
  • 🎮Steam / vlc

因為攜帶便利,現在主要只玩 NS 上的遊戲。Steam 上看到喜歡的遊戲,也盡量等 NS 上出了再買。

📱 Android 手機

  • 瀏覽器:Firefox for Android (Nightly)
  • 網頁更新通知:Web Alert
  • 閱讀:Palabre (feedly), Readmoo
  • 稍候閱讀:Pocket
  • 信箱:Gmail, Inbox
  • 地圖:Google 地圖
  • 記事:Keep
  • 內建相機,內建時鐘
  • 相簿:Dropbox, Google 相簿
  • 社交:Facebook, LINE, Twitter, WeChat
  • 待辦事項:Todoist* 密碼管理:LastPass
  • 記帳: Toshl
  • 線上影片:Youtube
  • 有聲書:Audible
  • 音樂:豆瓣 FM
  • 健康:小米運動,Pokemon Go

工具

  • 公事:Expensify, Duo Mobile
  • 旅遊:Google 翻譯,TripAdvisor
  • 影片播放:MX Player, DS video (少用)
  • 記錄看書狀況:Readmoo 分享書
  • 線上學習:Udemy, Pluralsight
  • IFTTT
  • 💳街口支付
  • 拼字訂正:Grammarly

Reference

· 8 min read

以太坊 (Ethereum) 是近幾年才發展起來的一種新的底層區塊鏈技術。以太幣 (Ether) 是以太坊公有鏈上產生的🔒💵加密貨幣 (Crypto Currency),除了可以拿來像比特幣 (Bitcoin) 一樣做交易外,還具有實際的用途。

以太坊和比特幣一樣是基於 P2P 網路與密碼學建立起的區塊鏈機制,不同之處是,以太坊在每個運作的節點上都運行著一個以太坊虛擬機 (Ethereum Virtual Machine, EVM),可以用來執行完整的程式。這些程式在以太坊中被稱為⚖📒智能合約(Smart Contract)。智能合約除了可以處理資料,還內建轉帳功能,可以很容易地透過智能合約來交易加密貨幣。由於智能合約可在每個以太坊的節點上執行並進行驗證,所以計算結果被認為是可信任的。以太坊還開發出了web3.js讓開發者可以使用網頁技術撰寫智能合約的操作介面。這樣的網頁操作介面又稱為🕸🅰分散式應用程式(DAPP)。要使用 DAPP,必須在支援 DAPP 的瀏覽器中才能使用 (如MistParity)。

使用智能合約技術製作的服務,也構成了以太坊生態圈的一環。例如Ethereum Name Service(ENS)就提供了讓使用者更容易尋找到轉帳對象、智能合約,和 DAPP 的方式。

以太坊提供了便於交易的加密貨幣以太幣 (Ether),可透過智能合約解決交易上的信任問題,同時也可撰寫 DAPP 來提供友善的資訊彙總與操作介面,讓以太坊成為一個目前最理想的區塊鏈底層技術。

graph TD DAPP -.- DAPP瀏覽器 DAPP瀏覽器 -.- 智能合約 錢包 -.- 智能合約 智能合約 --- 以太坊 錢包 -.- 以太幣 以太幣 --- 以太坊 以太幣 --- 激勵機制 以太坊 --- P2P 以太坊 --- 共識機制 共識機制 --- 密碼學 P2P --- 網際網路 分散式APP -.- ENS 智能合約 -.- ENS 以太幣 -.- ENS

以太幣 (Ether) 的實際用途

在電腦上執行的一般的程式碼,寫出來可能會有迴圈不斷執行 (死迴圈) 的情況,搬到區塊鏈上亦然。那麼以太坊怎麼解決這個問題呢?以太坊開發者想到的辦法是讓執行的程式碼變得有價。EVM 裡支援的所有的指令 (OPCODE) 都有明碼標價,執行智能合約需要消耗與執行的指令數量相當的以太幣。在智能合約的術語中,這些拿來消耗的以太幣被稱為 "gas"(燃料)。部署合約到區塊鏈上時,需要附加一定數量的燃料。當燃料消耗完而程式還沒執行完,就會出現 "Out of Gas"(燃料耗盡) 錯誤。智能合約透過這樣的方式來避免死迴圈等情況。

智能合約能做什麼事?

創造新的加密代幣

智能合約最基本的應用,就是做出新的加密代幣!只要遵循一定的規範(ERC20),部署一份智能合約到以太坊區塊鏈上,任何人都可以可以很容易地創造出自己的加密代幣。

不用像比特幣的山寨幣一樣需要自行徵募礦工。你的加密代幣會以 "以太坊的一個智能合約" 的形式存在於以太坊的區塊鏈中。現有支援以太幣的錢包與交易所,也可以快速地接入你的加密代幣。只要你發行的加密代幣與代幣背後所代表的服務具有交易的價值,代幣也可能變貨幣。

募資

此外,在募資上,智能合約也有無與倫比的優勢。新創公司ICO可透過以太坊的智能合約,在收到資助者的以太幣時,自動發出等值的加密代幣。

由於這些加密代幣可交易,如果公司的服務有價值,早期投資人在投資的前期,就可以透過交易加密代幣來調整持有量。

普通的投資人也第一次有機會直接支持自己感興趣的創業者,並可能從而獲得豐厚 (或歸零) 的回報。

程式能做的事

當你需要公開,可被信任的紀錄時,都可以透過智能合約達成。

以太坊的缺點

目前以太坊區塊鏈的速度和電腦執行速度無法相比,不適合快速交易,或是需要儲存較大資料的情境。近期的plasma提案有望解決快速交易的問題。

因為缺乏即時調控區塊大小的手段,在一些很熱門的交易時段 (如某些熱門的 ICO 開放認購時),整個網路的交易延遲會變地很長。

智能合約一經部署就永遠存在,除非擁有者啟動智能合約中的自毀 (selfdestruct) 功能。如何升級合約並保存其中的參數與代幣,是一個值得探討的課題。

以太坊網路節點上並不適合儲存較大的檔案。目前有SwarmIPFS等分散式檔案儲存方式可供選擇。

其他參考資料

· 11 min read
聲明:gasolin.eth 此 Domain 已過期,我並未繼續註冊

前幾天剛拿到gasolin.eth這個 ENS 網域。ENS (Ethereum Name Service)1 的功能類似我們較熟悉的 DNS (Domain Name Service) 網域名稱服務,但提供的不是 Internet 網址,而是將以太坊 (Ethereum) 錢包地址和智能合約地址以xxxxxxx.eth網址的方式表示,可以用於轉帳或存取智能合約等地方。

ENS 網域的應用情境

例如有人想轉錢給我,就可以請他將以太幣轉到gasolin.eth這網址,gasolin.eth會自動轉址到我指定的錢包地址 (0x....),轉帳的人不需要記憶一串根本像亂碼的以太幣錢包地址。

Imgur

若我想要公開智能合約讓大眾使用,我可以公開諸如service.gasolin.eth這樣的網址,使用者只要連到service.gasolin.eth,就會自動轉到對應的智能合約地址。若這個智能合約所提供的是單次服務,我也可以透過修改service.gasolin.eth對應的智能合約地址,來 "升級" 這個智能合約服務。使用者依然是連到service.gasolin.eth使用這個服務,而不需要了解背後的機制。

查詢可申請的網域

因為gasolin.eth已經被我申請了,查詢可申請地址這部分將以搞笑的 NMB (嫩模幣) ICO3為例,我會以申請nenmocoin.eth當做例子,介紹整個申請 ENS 網域的流程。

嫩模幣的投資條件是本次投資僅接受ETH,最少投資額0.0.1ETH,ETH錢包地址:0x74b7bafafd200a58e79b719f3565cbb43af7d6b7。如果能將0x74b7bafafd200a58e79b719f3565cbb43af7d6b7換成nenmocoin.eth,投資者轉帳起來就更直覺了。

在寫作時nenmocoin(https://registrar.ens.domains/#nenmocoin) 這個網域是可以申請的 (目前 ENS 僅接受申請 7 個字母以上的網域)。

想查詢可用的網域,可以前往 http://registrar.ens.domains/ 或連到MyEtherWallet2並切換到ENS分頁,查詢可用的 ENS 網址。

Imgur

如果在一般瀏覽器中查看,會看到黃色欄的警告提示。

Imgur

這是因為 ENS 服務是跑在以太坊 Ethereum 區塊鏈上,要麼用專用的 browser(如 Mist),不然就是裝 Parity,或瀏覽器擴充套件 MetaMask (Chrome only)。還有個選擇就是用MyEtherWallet網頁錢包,裡面內建註冊 ENS 需要的功能。

我是使用MyEtherWallet網頁錢包來完成整個註冊 gasolin.eth 網域的流程。

競標網域須知

  • 註冊 ENS 網域並不需要實名或其他認證流程,只要有一個以太幣錢包地址即可。
  • 請參考參與首次代幣發行 (ICO) 時要知道的事,絕對不要用交易所提供的錢包競標網域,不然即使競標到網域也會變成交易所的 XD。
  • ENS 網域的最低起標價是 0.01ETH (當前匯率是美金 $2~3)

要註冊 ENS 網域,需要遵循 ENS 網域競標流程 (bid)。

ENS 網域競標流程模擬現實的競標,首先是寫下標價,並將相應數量的以太幣傳入 ENS 票箱。兩天後就可以公告這個網域競標 (揭標),其他人能看到這個網域已經開始競標了。如果他們有興趣,也可以加入這個網域的競標。最終價高者得,但出價最高的人只需要繳交第二高者的標價。ENS 會自動退回所有參與者的標金,也會返回得標者標金的差額。如果得標者一年後未續約,ENS 將釋出此網域並退回押金。

graph LR 網域可註冊 --> 提出標金 提出標金 -- 2 天 --> 公告競標 公告競標 -- 2 天 --> 取得網域 取得網域 -. 1 年後未續約 .-> 釋出網域並退回押金

提出標金

確定 "nenmocoin" 網域可用,接下來就是打開錢包,開始競標吧。

Imgur

打開錢包,輸入超過最低起標價 0.01ETH 的數字,勇敢按下Start an Auction按鈕,並照著指示完成競標手續。

記得將畫面上的資料複製留存,後面的手續中會用到。 完成競標手續後會進入 2 天的等待期。

公告競標

Imgur

其實照著MyEtherWallet上面的說明完成公告手續並不困難😤。最重要的事,就是在 2 天的等待期結束後,

記得回來公告競標, 記得回來公告競標, 記得回來公告競標,

如果沒做這個動作,前幾天提出的標金會被送到黑洞消失掉,沒辦法取回喔!我第一次試著註冊網域的時候就這樣被吃掉 0.01ETH😭。

公告後其他人可以看到網域開始競標的訊息。這時有兩天的時間讓其他感興趣的人一起競標,當前最高價會顯示在查詢頁面上。

取得網域

公告期結束後,如果順利取得網域,可以看到如下訊息

Imgur

這時 記得回來宣告取得網域, 記得回來宣告取得網域, 記得回來宣告取得網域,

照著MyEtherWallet上面的說明完成宣告手續後,才能正式取得這個網域。

以後其他人查詢時,就會看到這個網域已經被註冊的訊息。

取得網域之後

取得網域之後,在MyEtherWallet上查看網域並打開錢包,就會看到如何設定網域的說明。

目前設定網域的方式比較複雜些,需要到Contracts(合約) 目錄下,在Select Existing Contract(選擇已經存在的合約)選擇ENS - Public Resolver,並在Read/Write Contract(讀取 / 寫入合約) 部分選擇setAddr(設定地址) 功能,照著設定網域說明將錢包地址輸入,這樣網域才能正確解析到我們想要的錢包地址。

Imgur

如何節省交易手續費

以上整套設定 ENS 的過程牽涉到 5~6 次交易。只有第一次需轉出標金,後面的各種動作都只收交易手續費。因此註冊一個 ENS 網域的成本其實是標金 + 多次手續費。標金在到期之後會返還,因此實際影響持有成本最大的是交易手續費。

MyEtherWallet右上角預設的交易手續費是 21GWei(1 Ether = 10^9 GWei)。手續費是給分礦工(提供計算力協助以太幣記帳的人)的,調低的話,交易確認的速度會變慢,調高則變快。我剛開始不懂,因此就使用了預設值。後來看 Youtube 上的教學,才知道可以參考Gas Station網站即時的SafeLow Cost(最低安全交易手續費)來設置。只要我們提供的手續費高於這個數目,交易都會成功。

Imgur

這陣子最低手續費大多是 3 ~ 5 GWei。我照這個手續費做設定(並斟酌提高 1 ~ 2 Gwei)交易都有成功。雖然不管用什麼標準來算,以太坊的手續費都已經很便宜,但多一步簡單的操作,就能感受到精打細算的樂趣。

結語

上面舉了嫩模幣 ICO 的轉帳地址當做例子。我故意把引用的嫩模幣錢包地址,換成了我自己的錢包地址。如果不提,應該沒幾個人會注意到吧? 如果錢包地址改用本文提到的nenmocoin.eth,參與者是不是更容易發現收款地址已被修改了呢? ENS 並沒有做身分認證,釣魚網站也可以申請相似的 ENS 域名來釣魚,要避免這樣的情況,也有賴服務提供者有在提供服務前,有優先註冊域名的保護意識。

ENS 本身其實就是一系列基於以太坊的智能合約4,內部的流程都是自動的,對於智能合約與 DAPP 開發者來說,也是很值得參考的架構。

參考資料


gasolin.eth這個網址真的可以用喔!覺得這篇文章寫得蠻好想打賞一下,可以傳到我的錢包地址gasolin.eth