為何發送 ERC20 Token 需要兩次交易? <8> 文組也該知道的區塊鏈技術知識

Blockchain Technical Overview <8> Transfer of ERC20 Token

Vins Lai @AuroraCard
Pelith
9 min readNov 27, 2019

--

收看本系列文章的讀者,應該都對於區塊鏈的基本原理和架構有些概念,如果沒有,推薦您先去 Google 搜尋 區塊鏈、比特幣、以太坊這些關鍵字了解一下。我們將在這些基礎概念之上,來談區塊鏈的技術知識。本系列文章並不會談到太深的技術鑽研,而是希望以深入淺出的方式讓每一個想要搞懂區塊鏈技術的人都能在讀完後說出:原來如此!

本系列文章由區塊鏈技術解決方案開發公司:Pelith 編撰。內容皆經過諸位區塊鏈資深研究員及開發者校對與驗證,盡可能確保內容正確無誤,讓讀者能安心吸收正確的區塊鏈技術知識

為什麼發送 ERC20 Token 給別人需要兩次交易?

許多人可能對此感到疑問,透過本篇文章相信能充分為您解惑。上一節 我們帶大家一窺以太坊的架構全貌並為迄今為止七篇文章做了小結。我們將在這基礎之上闡明發送 ERC20 Token 背後的技術解析。

發送以太幣

發送以太幣時其實蠻符合我們的直覺,就是把錢發給別人,別人收到這樣。然而發送 ERC20 代幣卻彷彿不是這麼單純,為什麼呢?

EOA 互動(發送 ETH)

ERC-20 代幣的本質

首先回顧一下 上一節 提到的,ERC20 代幣只是用 ERC20 之智慧合約底下的記憶體來儲存記錄各個地址持有數量的帳本。既然對象是個智慧合約,就要再回顧一下 第二節 提到的,個人帳戶(Externally Owned Account, EOA)與 合約帳戶(Contract Account)的不同,由於智慧合約沒有主觀意識,動作皆需要由 EOA 發交易來觸發。因此當合約地址收到 ETH 外的其它代幣時,它並不會知道。因為更動的是「另一個智慧合約底下的記憶體」

EOA 與 合約帳戶

我們實際來看一個範例:

假設我想要透過去中心化交易所 Uniswap 將我持有的 82 顆 cDAI 兌換成 0.0092 顆 ETH,在技術上是如何做到的呢?

先備知識:cDAI 是我將 DAI 存入 Compound 放貸後,Compound 發回給我的 ERC20 Token。所以 cDAI 是由 Compound 管理的 cDAI 智慧合約底下之記憶體(帳本)來記錄追蹤的。

Uniswap 的 Token Swap 介面

我的 Token Swap 需求在常規邏輯上是:
我把我的 cDAI token 發送給 Uniswap,Uniswap 把 ETH 發送給我。

不過事情並非這麼單純。由於 Uniswap 是去中心化,由智慧合約來運作的。因此當 Uniswap 收到了 cDAI token 時,它不像人一樣可以點開 Metamask 去查看是否有收到,確認有收到後再把 ETH 發送給我,因此需要用特殊的做法來實現這樣的流程。

我們就直接開門見山講答案

用比喻來說明的話,做法是:

  1. 我先到 銀行(ERC20 Token 的智慧合約)開啟 授權
    允許 對方(第三方智慧合約)能夠到我的戶頭
    提取 錢(ERC20 Token),並設定「能夠提取的額度」
  2. 接著我開給對方一張「寫上金額的支票」
    讓對方拿著支票到 銀行 中提領我帳戶中的 錢。

因為對象(智慧合約)是一段程式碼,如此做法方能 讓智慧合約確認提取到 Token 並執行後續的合約邏輯操作。

因此,回到區塊鏈的世界,必須透過以下兩個交易步驟來進行:

Tx1: Approve(授權)

我必須先發一筆交易到「Compound cDAI Token 智慧合約」(銀行),
授權「Uniswap 的 cDAI to ETH 交易對智慧合約」(對方)
可以到「Compound 的 cDAI Token 智慧合約」
(銀行)
提取我的「cDAI Token」(錢)

Tx2: Swap Token(兌換)

隨後,我再發送一筆「將 cDAI 兌換為 ETH」的交易(支票)
到「Uniswap 的 cDAI to ETH 交易對智慧合約」(對方)觸發,
讓「Uniswap 的 cDAI to ETH 交易對智慧合約」(對方)
至「Compound 的 cDAI Token 智慧合約」(銀行)
提領我的 82 顆「cDAI Token」(錢)。
「Uniswap 的 cDAI to ETH 交易對智慧合約」(對方)提領到 Token(錢)後再將 0.0092 顆 ETH 發送給我。

如下方示意圖所示:

接著我們帶大家實際走一次操作流程以搞懂背後技術邏輯。

Tx1: Approve(授權)

首先,當我們來到 Uniswap 交易所,選好 Input 與 Output 的加密貨幣種類並在 Input 輸入欲兌換的數量,便可以在我欲兌換成 ETH 的 cDAI Token 旁邊看到「Unlock」的按鈕。這就是要求我進行「Tx1:授權」的操作。

點選「Unlock」按鈕後,Metamask 便會跳出「批准」的交易來讓我簽署。一但簽署後,我便批准了 Uniswap 能夠到 Compound 提領我的 cDAI 的權限。

這筆交易被確認後,我們便可以憑 Txn Hash 到 Etherscan 上找到這筆交易。可以發現這筆交易是發給「Compound 的 cDAI ERC20 Token 智慧合約」

點進去這筆交易後,便可以看到呼叫的正是 approve 的 function。我同意了「Uniswap 的 ETH-cDAI 交易對」合約地址能夠來提領我的 cDAI,而授權的提領金額量為「最大」

可能會有些人好奇為什麼不把 amount 設成我要兌換的量:82 就好。原因是為了便利於未來提領操作時不用再次授權,通常呼叫智慧合約的 approve 函式時都會預設為開啟最大值,這樣未來再次需要提領時就不用再次進行 approve 的操作。

然而要注意的部分是:針對「可能存在漏洞或不被信任的智慧合約」,若是仍按照預設將權限開至最大值,則將面臨 Token 遭到竊取的風險。

在完成「Tx1:Approve 授權」後,便可以看到「Unlock」的按鈕消失,並且「Swap」按鈕已能夠點選。

Tx2: Swap Token

接著便能夠來進行將我的 cDAI 兌換成 ETH 的 Swap Token 動作。

同樣透過 Metamask 來簽署完成這筆交易後,我們到 Etherscan 上追縱這筆交易:能夠發現這筆交易是從我的錢包發送給「Uniswap 的 ETH-cDAI 交易對 智慧合約」

點進去這筆交易後可以看到在這筆交易中執行了兩件事:

  1. 將 82 cDAI 從「Compound 的 cDAI 智慧合約」轉至 「Uniswap 的 ETH-cDAI 交易對合約地址」中。
  2. 將 0.0092 ETH 從「Uniswap 的 ETH-cDAI 交易對合約地址」中轉給我。

接著我們可以在「Uniswap 的 ETH-cDAI 交易對合約地址」的
「Internal Txns」中看到 0.0092 ETH 轉移至我的錢包地址;以及
「Erc20 Token Txns」中看到 82 cDAI 從「Compound 的 cDAI 智慧合約」轉移至「Uniswap 的 ETH-cDAI 交易對合約地址」中。

同時,這筆交易在「Compound 的 cDAI 智慧合約」中也可以查看到 82 cDAI 被轉移出的記錄。

結論

  1. 發送 ETH 與 發送 ERC20 Token 給智慧合約有本質上的差異。ETH 是 push-based,單純把 ETH 發過去就可以。ERC20 Token 的發送則是 pull-based,讓合約去主動提取 Token。
  2. 必須先發送一筆交易至 ERC20 合約進行 授權(Approve),允許某合約地址能夠至 ERC20 智慧合約提取我持有的 ERC20 Token。
  3. 再發送一筆交易來觸發合約地址進行 提取 ERC20 Token 與後續的邏輯操作。

至此,相信讀者都已充分理解發送 ERC20 Token 給智慧合約背後的技術邏輯。

下一節我們將來介紹「Oracle(預言機)」,這個扮演 真實世界與區塊鏈間橋樑 的技術,並帶大家認識 MakerDAO、Compound 等大專案的實作方式。敬請期待!

以上,若有任何

A. 我寫得不夠清楚的地方
B. 撰寫上改進的建議
C. 希望我能夠撰寫分享的區塊鏈技術知識內容

都非常歡迎在底下留言回覆。希望我的文章能幫助到更多像我一樣想學習區塊鏈技術與知識的朋友。如果您覺得讀完有所收穫,也希望能
*不吝嗇給我 Like / 50 claps
*分享給您的朋友們
謝謝大家!

--

--

Vins Lai @AuroraCard
Pelith
Editor for

Co-Founder of Aurora Card - World's First Crypto Credit Card built on Trust with supreme Privacy, sign up: https://app.aurora-card.com/signup?userRef=N527Zi