近來以太坊上最火爆的領域就是DeFi。主要的DeFi 應用包括ERC20 代幣的借貸、質押和交易。若想在Uniswap、Aave 和Yearn 等DeFi 協議上使用ERC20 代幣,你需要授權dApp 來使用這些代幣。這就是所謂的 *ERC20 授權* 。這些授權對於DeFi 平台的運作來說必不可少,但是如果不加以控制,那將是非常危險的。
ERC20 授權的必要性
有了以太坊上的原生代幣ETH,你就可以將ETH 發送至該智能合約,同時調用智能合約功能。這是通過所謂的可支付函數(payable funtion)實現的。但是,由於ERC20 代幣本身就是智能合約,你無法通過直接將代幣發送到智能合約來調用其函數。
因此,ERC20 標準讓智能合約使用 transferFrom() 函數代表用戶轉移代幣。為此,用戶需要允許智能合約代表他們轉移代幣。
這樣一來,用戶就可以將代幣“存入”智能合約,同時智能合約會更新其狀態來顯示這筆存款。相反,如果你將ERC20 代幣發送至該智能合約,則合約不會更新其狀態(例如,將這筆存款記入你的賬戶)。

例如,如果你將DAI “存入” Aave 來賺取利息,你首先要允許Aave 合約從你的錢包中取出一些DAI。然後你調用Aave 合約裡的函數,指定你想要存入的DAI 的數量。然後,Aave 合約使用 transferFrom() 函數從你的錢包中取出相應數量的DAI,並將同等數量的aDAI 代幣記入你的賬戶。
無限ERC20 授權的危害
將特定數量的ERC20 代幣(如100 DAI)存入合約時,你就可以選擇將授權額設成這個數量。然而,許多應用會向用戶要求無限授權。
這會帶來極好的用戶體驗,因為用戶不需要在每次存款時重新授權。設置無限授權後,用戶只需要同意一次,之後存款時就不會再重複這一過程。
但是,該設置存在很大的弊端。眾所周知,即使是成熟的項目,也有可能存在漏洞。一旦你給了這些平台無限授權,不只是你的存款會陷入風險之中,你的錢包中的代幣也是如此。
在Devcon 5 上,我第一次與Paul Berg 談到了這個問題。在這次大會上,Paul 就本文所討論的問題做了陳述。在開發Sablier 時,Paul 在他的智能合約中發現了一個漏洞(已經修復了!),不僅所有存入該智能合約的DAI(100 美元)有風險,所有測試者的錢包中的DAI(1 萬美元) 也是如此!
實際風險
長期以來,無限授權的風險主要是理論上的。在Paul 所開發的Sablier 平台正式上線之前,這個漏洞就被修復了。當時,還沒有出現利用ERC20 授權的攻擊,但是只要平台繼續要求無限授權,遲早會出狀況。
去年,我們已經看到了幾起利用ERC20 授權的攻擊事件。
意外漏洞
今年早些時候,Bancor 出現了一個漏洞,危及用戶資金。執行ERC20 transferFrom() 函數的函數變成了public 屬性(不再是private 合約私有屬性),因此任何人都可以執行該函數,並取走用戶錢包中的資金。 Bancor 執行了一次白帽黑客攻擊,控制了損失,並將資金還給了用戶。
惡意利用漏洞
除了Bancor 的意外漏洞之外,還有很多惡意利用漏洞的情況。在今年夏天的DeFi 熱潮中,人們都在為各種以食物命名的DeFi 分叉產品狂歡,其中也包括一些騙局。即使人們為了規避風險只存入少量代幣,他們錢包中的代幣也會因為無限授權而陷入風險。

ZenGo 就在一個名為UniCats 的項目中發現了可利用漏洞。人們可以存入Uniswap(UNI)代幣,然後通過流動性挖礦獲得MEOW 代幣(MEOW 代幣是無法偽造的)。但是如果要存款,用戶必須提供 無限授權。如果項目遭到攻擊,攻擊者不僅可以拿走項目的存款,還可以拿走用戶錢包內的所有UNI 代幣。
另一個例子是Degen Money 項目。 Degen Money 項目採用了一種不怎麼高明(但還挺“有效”)的辦法。這個項目沒有開發自己的智能合約,而是創建了一個前端來進行兩次授權交易。一次是向一個運行中的智能合約,另一次是向完全不同的地址。
由於很多人沒有專門檢查錢包地址,這就導致攻擊者可以取走用戶錢包中的代幣。
那硬件錢包呢?
總的來說,硬件錢包比手機、手提電腦和基於瀏覽器的錢包安全的多。原因是,控制資金的私鑰安全地存儲在硬件錢包中,並且永遠不會離開該設備。因此,通過硬件錢包,你可以確保沒人能竊取你的私鑰。
ERC20 授權的問題在於,沒人需要竊取你的私鑰才能從你的錢包中取走代幣。因此,硬件錢包也無法防範本文所討論的惡意利用漏洞問題。
使用硬件錢包依然是一種好習慣,因為硬件錢包確實能保護你免受其它漏洞攻擊。但是,你需要注意的是,硬件錢包不能抵禦授權漏洞和其它很多智能合約漏洞。
dApp 開發者可以做些什麼?
在Devcon 的講話中,Paul 提到了一些關於無限授權問題的解決方案。這些方案各有優缺點。其中最實用的方案是即批即用模式。在這種模式下,應用只會要求用戶授權確切的數額,而非不限額。
這種方案的用戶體驗確實會差一些,因為每當用戶想要發送交易時,都需要發送一筆新的授權交易,不能再像無限授權那樣一勞永逸。這個模式的缺陷是會增加交易費成本,如果交易費像去年那樣暴漲,就會帶來很大的麻煩。
另一種替代型方案是,可以讓用戶選擇僅授權當下需要花費的數額,還是授權更高的數額以便後續進行更多交易。已經有多個項目採用這種策略,例如1inch.exchange 和Curve.fi。

另一個減少交易成本的解決方案是,採用EIP2612 之類的標準,讓用戶可以通過簽署消息來(免費)設置其授權額度,無需再通過發送交易的形式。但是,這類標準並未得到廣泛採用,而且圍繞該標準打造的工具也不多。
用戶可以做些什麼?
由於ERC20 授權是很多智能合約所不可或缺的部分,完全停止授權的方案並不可行。但是在可能的情況下,請盡量避免無限授權。
人們已經比一年之前更加了解這一問題,因此有些dApp 可以讓用戶選擇只授權當前需要花費的數額,但是大多數dApp 依然不行。儘管如此,高端用戶還可以通過Metamask 的界面來降低其授權額度。

在使用dApp 時,請你思考一下是否需要經常使用這個dApp,以及你是否信任這個項目(如果是,選擇無限授權),還是說你只會偶爾使用這個dApp,或者根本不信任這個項目(如果是,選擇小額授權)。無論是哪種情況,你最好都要定期(如,每月)查看你的授權額度,並取消對不再使用的dApp 的授權。

為便於檢查並撤銷這些授權,我開發了一種名為revoke.cash 的工具。通過這個工具,你可以查看地址的代幣餘額和授權額度,之後就可以輕而易舉地撤銷或降低授權。類似的工具還有approved.zone 等。
結論
許多去中心化應用的運行都離不開授權,但是無限授權通常並不利於安全性。 2020 年已經出現過幾起利用ERC20 授權的漏洞事件,人們對這個問題的認識比一年前深得多。作為一名用戶,你可以採取一些措施來降低上文所述風險,包括定期查看並撤銷多餘授權。
作者: Rosco Kalis
翻譯&校對: 閔敏& 阿劍

