header-langage
简体中文
繁體中文
English
Tiếng Việt
한국어
日本語
ภาษาไทย
Türkçe
掃碼下載APP
Partnered With:

如何解碼以太坊智能合約數據,並批量處理相關細節?

閱讀本文需 16 分鐘
一旦我們有了工具,解碼的過程就相對簡單了
原文標題:《Decoding Ethereum smart contract data》
原文作者:Yifei Huang,紅杉資本
原文編譯:ChinaDeFi




正如我們在之前的文章中所討論的,智能合約交易類似於智能合約驅動的 web3 應用程序中的後端 API 調用。每個智能合約交易和結果應用程序狀態更改的細節都記錄在稱爲交易、調用和日誌的數據元素中。交易數據元素表示用戶發起的函數調用 (更準確地說是 EOA),調用數據元素表示智能合約在交易中發起的其他函數調用,而日誌數據元素表示交易執行期間發生的事件。


使用這些數據元素,可以非常精細地描述由於交易而在應用程序和區塊鏈上發生的狀態更改。當對一個去中心化的 web3 應用程序的所有交易、跟蹤和日誌進行彙總分析時,可以提供用戶羣及其在產品中的活動的整體和深刻的觀點。然而,這樣做是有挑戰性的,因爲許多顯著的細節都被記錄爲十六進制編碼字符串。例如,在以太坊網絡上使用 Uniswap 交換一對 Token 的交易 (該特定記錄可以在 Etherscan 上查看):




如果在 Etherscan 上查看交易,就可能已經注意到,它已經解碼了這個原始記錄,並提供了很好的上下文來幫助我們理解交易細節。雖然這非常有幫助,但它並不是爲了回答那些需要轉換和彙總數據的問題,例如,所有 Uniswap 用戶的總交易價值是多少,或者 Uniswap 用戶 3 個月的留存率是多少。爲了回答這些問題,我們需要能夠收集所有記錄,對其進行解碼,並批量處理相關細節。我們將在接下來的文章中詳細介紹如何做到這一點。


解碼交易


如果我們檢查原始數據記錄,我們可以看到交易是由 EOA 發起的 0x3c02cebb49f6e8f1fc96158099ffa064bbfee38b,發送到與 Uniswap v2 路由器關聯的智能合約地址 0x7a250d5630b4cf539739df2c5dacb4c659f2488d。但是,相關請求詳細信息在 input 字段中被編碼爲一個長十六進制字符串。


在我們討論如何從 input 中提取人類可讀的數據之前,先談談它的結構將會很有指導意義。前導 0x 表示該字符串是十六進制的,因此它與實際的信息內容無關。之後,每 2 個十六進制字符代表一個字節。前四個字節,在本例中是 38ed1739,是被調用函數的哈希簽名。其餘字節是傳遞給函數的參數的哈希值。這意味着輸入字符串的長度可以根據所調用的特定函數和所需的參數而變化。


爲了解碼這個十六進制字符串,我們需要引用應用程序二進制接口或 ABI。這是一個 json 對象,包含給定智能合約的所有函數和事件接口定義 (即名稱和類型)。ABI 的功能是查找將交易數據中的散列簽名與人類可讀的接口定義進行匹配。ABI 示例如下所示:


Uniswap v2 路由器 ABI 的部分視圖


ABI 通常可以在像 Etherscan 這樣的區塊瀏覽器上找到,以及合約源代碼。這是 Uniswap v2 路由器合約的 ABI 鏈接。


一旦我們有了 ABI,我們就可以編寫來解碼交易:




在示例代碼中有幾點需要注意:


1. 此代碼設計用於批量處理大量交易。它假設數據已經存在於本地存儲中 (而不是從區塊鏈實時獲取),並且非常適合像 PySpark 這樣的分佈式處理框架。


2.@lru_cache(maxsize=None)—我們緩存合約對象創建,以減少在大量交易中重複相同計算的開銷。這假設解碼針對少量(數千個)不同的智能合約。


3. 它利用開源的 web3 包方法 decode_function_input 來基於 ABI 中提供的模板提取數據。然而,此方法返回的數據通常不可序列化的 (例如字節數組),有時還會丟失人類可讀的鍵。因此,使用實用程序方法執行提取後處理 convert_to_hex 將數據轉換爲可序列化的 json 對象並在缺失的地方附加人類可以理解的鍵是非常有幫助的(甚至可能是必要的)。這使得持久化和重用已解碼的數據變得更加容易。


4. 同樣的代碼也可以用於解碼跟蹤數據元素。這是因爲它們只是由智能合約發起的內部交易。


使用上面的代碼可以得到這個已解碼的輸入數據


function called: swapExactTokensForTokens arguments: { "amountIn": 2500000000, "amountOutMin": 194024196127819599854524737, "path": [ "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "0x528B3e98c63cE21C6f680b713918E0F89DfaE555" ], "to": "0x3c02cebB49F6e8f1FC96158099fFA064bBfeE38B", "deadline": 1634603299 }


這樣我們就更容易理解了。


1. 該調用是對名爲 swapexacttokensfortokens 的方法的調用,用戶正在放入 25 億單位的起始 Token,並期望至少返回 194,024,196,127,819,599,854,524,737 單位的目標 Token。這些數字看起來可能是天文數字,但請記住,Token 單位通常用 1/10^n 表示,其中 n 大約是 18。N 有時被稱爲 Token 的十進制值。


2. 該 path 數組描述了在此交易中交換的 Token。每個數組元素都是 Token 合約的地址。第一個是 USDC(一種與美元掛鉤的穩定幣),第二個是 Wrapped Eth(帶有 ERC20 接口的以太坊),第三個是 DXO(一種深空遊戲貨幣)。


3. 將 1 和 2 放在一起,我們可以推斷用戶請求交換 2,500 USDC (USDC 的十進制值爲 6) 和大約 1.94 億 DXO (DXO 的十進制值爲 18)。由於這種特殊的成對交換不能直接獲得,交易將通過 WETH 的中間 Token 進行調解。


解碼日誌


該交易在執行過程中還觸發了 7 個事件,可以通過 logs 在以太坊上查詢 Google 的 Public Dataset 中的表獲得,也可以通過 Etherscan 查看。與用戶所要求的交換相對應的兩個最顯著的記錄是:


log_index: 47 transaction_hash: 0x87a3bc85da972583e22da329aa109ea0db57c54a2eee359b2ed12597f5cb1a64 transaction_index: 37 address: 0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc data: 0x000000000000000000000000000000000000000000000000000000009502f90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000093f8f932b016b1c topics: [ '0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822', '0x0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d', '0x000000000000000000000000242301fa62f0de9e3842a5fb4c0cdca67e3a2fab'] block_timestamp: 2021-10-19 00:00:18 block_number: 13444845 block_hash: 0xe9ea4fc0ef9a13b1e403e68e3ff94bc94e472132528fe8f07ade422b84a43afc


還有


log_index: 50 transaction_hash: 0x87a3bc85da972583e22da329aa109ea0db57c54a2eee359b2ed12597f5cb1a64transaction_index: 37 address: 0x242301fa62f0de9e3842a5fb4c0cdca67e3a2fab data: 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000093f8f932b016b1c000000000000000000000000000000000000000000a137bb41b9113069a51e190000000000000000000000000000000000000000000000000000000000000000 topics: [ '0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822', '0x0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d', '0x0000000000000000000000003c02cebb49f6e8f1fc96158099ffa064bbfee38b'] block_timestamp: 2021-10-19 00:00:18 block_number: 13444845 block_hash: 0xe9ea4fc0ef9a13b1e403e68e3ff94bc94e472132528fe8f07ade422b84a43afc


同樣,相關詳細信息在 topics 和 data 字段中編碼爲十六進制字符串。與 transaction 的情況一樣,input 瀏覽這些數據字段的結構是有益的。topics 是一個數組,其中第一個元素表示事件接口定義的哈希簽名。topics 數組中的任何其他元素通常是事件中涉及的區塊鏈地址,根據具體上下文可能存在,也可能不存在。data 表示事件參數值,其長度根據事件定義而不同。與交易的情況一樣,我們需要引用合約 ABI,以便將其轉換爲人類可讀的形式。


敏銳的讀者會注意到上面日誌中的合約地址 0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc 和 0x242301fa62f0de9e3842a5fb4c0cdca67e3a2fab 與用戶 EOA 最初調用的 Router v2 合約 0x7a250d5630b4cf539739df2c5dacb4c659f2488d 不同。這兩個地址對應 USDC-WETH 和 DXO-WETH Token 對的 Uniswap v2 對合約。這些合約負責持有各自交易對的流動性,並實際進行交換。用戶最初與之交互的 Router 合約作爲一個協調器,並向適當的配對合約發起內部交易 (跟蹤)。因此,爲了解碼這些事件,我們還需要一對合約 ABI。解碼日誌示例如下:




與交易解碼的代碼類似,示例代碼針對批量解碼用例進行了優化,並與類似 PySpark 的東西一起使用,以處理大量日誌事件。運行以上收益率:


event emitted: Swap arguments: { "sender": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", "to": "0x242301FA62f0De9e3842A5Fb4c0CdCa67e3A2Fab", "amount0In": 2500000000, "amount1In": 0, "amount0Out": 0, "amount1Out": 666409132118600476 }


還有


event emitted: Swap arguments: { "sender": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", "to": "0x3c02cebB49F6e8f1FC96158099fFA064bBfeE38B", "amount0In": 0, "amount1In": 666409132118600476, "amount0Out": 194900241391490294085918233, "amount1Out": 0 }


我們可以認爲這兩個確實 swap 是 path 在初始請求之後發生的事件——USDC > WETH > DXO。我們可以看到路由器合約 (以 488D 結尾) 是兩個事件中的發送方,充當協調者。USDC-WETH 對合約 (以 c9dc 結尾) 將 25 億單位 USDC 換成 666,409,132,118,600,476 單位 WETH,然後將產生的 WETH 轉移到 DXO-WETH 對合約 (結束 2Fab)。DXO-WETH 合約將 666,409,132,118,600,476 單位的 WETH 置換爲 194,900,241,391,490,294,085,918,233 單位的 DXO,並按照最初的要求將其發送回用戶 (EOA 結束於 E38B)。


結束語


正如本例所示,一旦我們有了工具,解碼的過程就相對簡單了,但知道要解碼什麼以及如何解釋結果數據就不是那麼簡單了。根據我們嘗試回答的具體問題,某些功能和事件比其他功能和事件更相關。爲了分析 web3 應用程序中的經濟活動和用戶行爲,瞭解特定智能合約的工作方式並確定感興趣的指標中涉及的關鍵功能和事件非常重要。這最好是通過實際使用該產品、在像 Etherscan 這樣的區塊瀏覽器上檢查數據消耗以及閱讀智能合約源代碼的組合來實現。這是制定正確的解碼和分析策略的關鍵條件。


原文鏈接


歡迎加入律動 BlockBeats 官方社群:

Telegram 訂閱群:https://t.me/theblockbeats

Telegram 交流群:https://t.me/BlockBeats_App

Twitter 官方帳號:https://twitter.com/BlockBeatsAsia

举报 糾錯/舉報
選擇文庫
新增文庫
取消
完成
新增文庫
僅自己可見
公開
保存
糾錯/舉報
提交