EIP-3074 為以太坊帶來了很多新的可能。
作者:Maarten Zuidhoorn;翻譯&校對: 閔敏&阿劍;原標題:《EIP-3074:提升以太坊用戶體驗》
如果你是以太坊上的活躍用戶,那麼你大概率會持有一些(ERC 20)代幣,用來與以太坊生態中的各種DeFi 項目進行交互。但是,這麼做的前提是你必須持有ETH,因為ERC 20 代幣無法用來支付以太坊的手續費。另外,在向智能合約發送代幣時,你通常需要執行兩個事務:一個用來許可目標合約使用你的代幣,另一個用來將代幣轉移到目標合約中。
EIP-3074 可以讓智能合約代表外部賬戶(就是普通的以太坊地址)發送事務,從而解決了上述乃至更多問題。
EIP 3074 引入了AUTH 和AUTHCALL 這兩個EVM 指令。第一個指令基於ECDSA 簽名設置環境變量authorized,第二個指令則作為authorized 發送調用。這本質上就是向智能合約授予外部賬戶的控制權。
通過AUTH 和AUTHCALL EVM 指令(又稱操作碼),智能合約可以基於已簽署消息獲得一個外部賬戶的授權,並代替該外部賬戶發送事務。這帶來了很多可能性,如:
-
贊助事務(又稱元事務):支付來自另一個賬戶的交易的gas。這樣一來,不持有ETH 的地址也能發送代幣。
-
批量事務:通過單個調用發送多個事務。這樣可以確保兩個或以上的事務在同一個區塊中執行,還可以降低交易費。
-
提升用戶體驗:例如,你可以在單個事務中調用approve 和transferFrom。
不同於現有的解決方案,EIP 3074 不需要智能合約錢包。你可以直接將事務發送給負責執行事務的調用者(invoker)。調用者是無狀態的免信任型智能合約,而且不需要你事先將餘額發送到智能合約。 EIP 3074 也沒有引入新的事務類型。從技術層面上來看,由於只引入了兩種新的EVM 指令,EIP 3074 實現起來理應更容易。
只可惜EIP 3074 依然在審查中,而且由於種種(安全方面的)擔憂,目前還不知道將於何時啟用。如果你現在想要體驗一把,可以使用Puxi 測試網。在本文中,我將詳細介紹EIP 3074 的工作原理。
如果你想看一下EIP 3074 的實際運行效果,我編寫了一個(批量)事務調用者合約作為示例。點擊下方鏈接,即可訪問:
https://github.com/Mrtenz/transaction-invoker
請注意,這個合約沒有經過審計,而且只是概念證明。請勿在生產環境中使用。
AUTH 和AUTHCALL 操作碼
EIP 3074 定義了兩個新的操作碼,可由智能合約調用:
-
AUTH(0xf6)—— 基於簽名和commit(提交)提出授權的外部賬戶。共有4 個輸入參數:commit以及簽名的yParity、r 和s。
-
AUTHCALL(0xf7) —— 代替已授權的外部賬戶發送調用(事務) 。共有8 個輸入參數:gas、addr、value、valueExt、argsOffset、argsLength、retOffset和retLength。與現有的CALL 操作碼相似。
確認外部賬戶的授權需要來自該外部賬戶的簽名消息。調用AUTH 的智能合約可以通過消息簽名復原出簽名者,然後將其設置成authorized EVM 環境變量。這樣一來,該智能合約每次調用AUTHCALL 時,調用者都會被設置成authorized地址。當被調用的智能合約調用CALLER(例如,通過Solidity 的msg.sender)時,將由已授權的外部賬戶的地址而非調用者地址(智能合約)執行調用。
發送一個或多個事務的基本流程如下圖所示:
– 上圖顯示了EIP 3074 的基本流程,其中調用者合約發送多個事務 –
-
外部賬戶簽署授權消息;
-
外部賬戶或其他gas 支付方將事務數據和授權消息發送給調用者合約;
-
調用者合約使用AUTH 操作碼執行授權,並使用AUTHCALL 操作碼發送事務。
將事務發送到合約的是誰並不重要,只要外部賬戶的簽名是有效的即可。因此,其他人(或賬戶)也可以發送事務。
請注意,目前無法使用EIP 3074 通過外部賬戶發送ETH。這樣做會極大地改變當前的一些重要假設,例如,檢查事務是否有效。調用者需要使用自己的ETH 餘額來發送ETH。但是,你可以將ETH 發送給調用者,並由調用者代為發送。目前,AUTHCALL 操作碼所包含的valueExt 字段必須被硬編碼成0。將來,如果找到適當的解決方案,我們可以更改這個字段,允許調用者外部賬戶發送ETH。
授權消息和commit
為了執行授權,外部賬戶必須簽署特定格式的消息:
0x03 || <填充的調用者地址> || <提交>
(注:|| 用作字節連接運算符。)
這個消息包含三個部分:一個魔術字節(0x03)、填充成32 字節的調用者地址(執行authorize的智能合約的地址)以及一個32 字節的commit。
– 授權消息格式,包含一個commit 示例 –
該commit 描述了外部賬戶提交的數據,並且可以根據調用的某些屬性計算得出,例如,地址、值和nonce 的哈希值。調用者合約可以根據屬性重新計算出commit,如果這些字段都正確的話,就會執行授權。
假設我們想要發送以下事務(JSON 格式):
我們可以對這些字段進行哈希計算(例如,用確定性的方式將它們連接起來,或使用EIP 712 之類的規範),並將得到的哈希值用作commit。
我們可以在智能合約中提供要發送的事務和授權消息的簽名,如JSON 數據所示。合約函數就如下面這個例子所示:
函數 sendTransactions(Transaction[] calldata 交易,簽名 calldata 簽名)外部;
智能合約根據transactions 重新計算commit,並將這個commit(連同簽名一起)提供給AUTH 調用。此舉的目的是找回簽名者的地址,如果計算得到的commit 無效,根據簽名找回的地址將是錯誤的,也就是說事務將失敗。
調用者對commit 的安全性負全責。你可以將0x0 作為commit 來簽署消息,並授予智能合約對外部賬戶的完整訪問權。前幾版EIP-3074 對commit 的格式要求更為嚴格,包括重放保護等,但是後面為了提高靈活性已經將其移除。這就要求你在與調用者進行交互時必須信任對方。
局限性和安全隱患
由於能夠根據簽名更改CALLER,EIP 3074 極大地改變了EVM 的運作方式。這會為新合約和現有合約引入潛在漏洞。因此,EIP 3074 已經經過正式審計。
下文解釋了一些安全隱患。由於種種原因,EIP 3074 建議只與可信調用者交互。 MyCrypto 等錢包界面提供可信調用者白名單功能。使用該功能的用戶只能為白名單內的調用者簽署授權消息。
弱commit 和重放攻擊
正如上文解釋的那樣,EIP 3074 沒有為commit 定義標準格式。調用者可以通過任意方式生成commit。這意味著,調用者有責任確保commit 的安全性,例如,抵禦重放攻擊。
如果commit 不包含某種隨機數,攻擊者就可以輕鬆獲取已簽署的消息,再一次發送給調用者。惡意調用者完全不需要驗證commit,就可以獲得外部賬戶的控制權。每次簽署消息時,請你務必謹慎。
EIP 3074 通過將調用者的地址包含在授權消息內,提供了最基礎的重放攻擊保護。這樣一來,惡意調用者就無法重放其他調用者的授權消息。
可升級調用者
EIP 3074 明確聲明調用者程序不可升級。如果調用者程序是可以升級的,攻擊者就可以部署另一個版本的調用者,在不驗證commit 的情況下授予合約對外部賬戶的控制權。
重入攻擊
目前,智能合約可以使用require(tx.origin == msg.sender) 來驗證事務是否來自外部賬戶(而非另一個合約)。這樣可以在一定程度上防止重入攻擊,因為它可以防止合約調用該函數。
EIP 3074 也允許tx.origin 成為授權消息的簽名者。調用者執行的任何AUTHCALL 都會導致tx.origin == msg.sender 成真,即使這個調用是由智能合約執行的,因此很有可能遭到重入攻擊。 EIP 3074 指出:“……本EIP 的作者並未找到任何有關這種重入攻擊的例子,儘管沒有進行詳盡的搜索。”
結論
EIP 3074 為以太坊帶來了很多新的可能。 AUTH 和AUTHCALL 使得外部賬戶能夠將賬戶的控制權授予智能合約調用者,從而實現批量事務和讚助事務等新的事務類型。然而,該EIP 也極大地改變了事務在以太坊上的運作方式,因此在主網上激活該EIP 之前,我們需要更深入地思考其安全性。
原文鏈接
展開全文打開碳鏈價值APP 查看更多精彩資訊