原標題:《解碼以太坊智能合約數據》
正如我們在之前的文章中所討論的,智能合約交易類似于智能合約驅動的web3應用程序中的后端API調用。每個智能合約交易和結果應用程序狀態更改的細節都記錄在稱為交易、調用和日志的數據元素中。交易數據元素表示用戶發起的函數調用(更準確地說是EOA),調用數據元素表示智能合約在交易中發起的其他函數調用,而日志數據元素表示交易執行期間發生的事件。
使用這些數據元素,可以非常精細地描述由于交易而在應用程序和區塊鏈上發生的狀態更改。當對一個去中心化的web3應用程序的所有交易、跟蹤和日志進行匯總分析時,可以提供用戶群及其在產品中的活動的整體和深刻的觀點。然而,這樣做是有挑戰性的,因為許多顯著的細節都被記錄為十六進制編碼字符串。例如,在以太坊網絡上使用Uniswap交換一對代幣的交易(該特定記錄可以在Etherscan上查看):
如果在Etherscan上查看交易,就可能已經注意到,它已經解碼了這個原始記錄,并提供了很好的上下文來幫助我們理解交易細節。雖然這非常有幫助,但它并不是為了回答那些需要轉換和匯總數據的問題,例如,所有Uniswap用戶的總交易價值是多少,或者Uniswap用戶3個月的留存率是多少。為了回答這些問題,我們需要能夠收集所有記錄,對其進行解碼,并批量處理相關細節。我們將在接下來的文章中詳細介紹如何做到這一點。
解碼交易
如果我們檢查原始數據記錄,我們可以看到交易是由EOA發起的0x3c02cebb49f6e8f1fc96158099ffa064bbfee38b,發送到與Uniswapv2路由器關聯的智能合約地址0x7a250d5630b4cf539739df2c5dacb4c659f2488d。但是,相關請求詳細信息在input字段中被編碼為一個長十六進制字符串。
在我們討論如何從input中提取人類可讀的數據之前,先談談它的結構將會很有指導意義。前導0x表示該字符串是十六進制的,因此它與實際的信息內容無關。之后,每2個十六進制字符代表一個字節。前四個字節,在本例中是38ed1739,是被調用函數的哈希簽名。其余字節是傳遞給函數的參數的哈希值。這意味著輸入字符串的長度可以根據所調用的特定函數和所需的參數而變化。
為了解碼這個十六進制字符串,我們需要引用應用程序二進制接口或ABI。這是一個json對象,包含給定智能合約的所有函數和事件接口定義(即名稱和類型)。ABI的功能是查找將交易數據中的散列簽名與人類可讀的接口定義進行匹配。ABI示例如下所示:
Uniswapv2路由器ABI的部分視圖
ABI通常可以在像Etherscan這樣的區塊瀏覽器上找到,以及合約源代碼。這是Uniswapv2路由器合約的ABI鏈接。
一旦我們有了ABI,我們就可以編寫來解碼交易:
importtracebackimportsysfromfunctoolsimportlru_cachefromweb3importWeb3fromweb3.autoimportw3fromweb3.contractimportContractfromweb3._utils.eventsimportget_event_datafromweb3._utils.abiimportexclude_indexed_event_inputs,get_abi_input_names,get_indexed_event_inputs,normalize_event_input_typesfromweb3.exceptionsimportMismatchedABI,LogTopicErrorfromweb3.typesimportABIEventfrometh_utilsimportevent_abi_to_log_topic,to_hexfromhexbytesimportHexBytesimportjsonimportredefdecode_tuple(t,target_field):output=dict()foriinrange(len(t)):ifisinstance(t,(bytes,bytearray)):output]=to_hex(t)elifisinstance(t,(tuple)):output]=decode_tuple(t,target_field)else:output]=treturnoutputdefdecode_list_tuple(l,target_field):output=lforiinrange(len(l)):output=decode_tuple(l,target_field)returnoutputdefdecode_list(l):output=lforiinrange(len(l)):ifisinstance(l,(bytes,bytearray)):output=to_hex(l)else:output=lreturnoutputdefconvert_to_hex(arg,target_schema):"""utilityfunctiontoconvertbytecodesintohumanreadableandjsonserializabledatastructures"""output=dict()forkinarg:ifisinstance(arg,(bytes,bytearray)):output=to_hex(arg)elifisinstance(arg,(list))andlen(arg)>0:target===k]iftarget=='tuple':target_field=targetoutput=decode_list_tuple(arg,target_field)else:output=decode_list(arg)elifisinstance(arg,(tuple)):target_field=foraintarget_schemaif'name'inaanda==k]output=decode_tuple(arg,target_field)else:output=argreturnoutput,{"inputs":,"name":"WETH","outputs":,"stateMutability":"view","type":"function"},{"inputs":,"name":"addLiquidity","outputs":,"stateMutability":"nonpayable","type":"function"},{"inputs":,"name":"addLiquidityETH","outputs":,"stateMutability":"payable","type":"function"},{"inputs":,"name":"factory","outputs":,"stateMutability":"view","type":"function"},{"inputs":,"name":"getAmountIn","outputs":,"stateMutability":"pure","type":"function"},{"inputs":,"name":"getAmountOut","outputs":,"stateMutability":"pure","type":"function"},{"inputs":","name":"path","type":"address"}],"name":"getAmountsIn","outputs":","name":"amounts","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":","name":"path","type":"address"}],"name":"getAmountsOut","outputs":","name":"amounts","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":,"name":"quote","outputs":,"stateMutability":"pure","type":"function"},{"inputs":,"name":"removeLiquidity","outputs":,"stateMutability":"nonpayable","type":"function"},{"inputs":,"name":"removeLiquidityETH","outputs":,"stateMutability":"nonpayable","type":"function"},{"inputs":,"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":,"stateMutability":"nonpayable","type":"function"},{"inputs":,"name":"removeLiquidityETHWithPermit","outputs":,"stateMutability":"nonpayable","type":"function"},{"inputs":,"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":,"stateMutability":"nonpayable","type":"function"},{"inputs":,"name":"removeLiquidityWithPermit","outputs":,"stateMutability":"nonpayable","type":"function"},{"inputs":","name":"path","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":","name":"amounts","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":","name":"path","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":","name":"amounts","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":","name":"path","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":,"stateMutability":"payable","type":"function"},{"inputs":","name":"path","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":","name":"amounts","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":","name":"path","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":,"stateMutability":"nonpayable","type":"function"},{"inputs":","name":"path","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":","name":"amounts","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":","name":"path","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":,"stateMutability":"nonpayable","type":"function"},{"inputs":","name":"path","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":","name":"amounts","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":","name":"path","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":","name":"amounts","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]'output=decode_tx('0x7a250d5630b4cf539739df2c5dacb4c659f2488d','0x38ed1739000000000000000000000000000000000000000000000000000000009502f900000000000000000000000000000000000000000000a07e38bf71936cbe39594100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000003c02cebb49f6e8f1fc96158099ffa064bbfee38b00000000000000000000000000000000000000000000000000000000616e11230000000000000000000000000000000000000000000000000000000000000003000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000528b3e98c63ce21c6f680b713918e0f89dfae555',sample_abi)print('functioncalled:',output)print('arguments:',json.dumps(json.loads(output),indent=2))
摩根溪聯合創始人:真正考驗是如何在未來10年持有BTC并保護其安全:摩根溪聯合創始人Jason Williams剛剛發推稱:“如果你現在有了比特幣,你已經完成了簡單的部分。真正的考驗是如何在未來10年持有和保護它的安全。比特幣將重塑我們所知道的一切。我真的不認為我夸大了這句話。”[2020/11/7 11:57:03]
在示例代碼中有幾點需要注意:
此代碼設計用于批量處理大量交易。它假設數據已經存在于本地存儲中(而不是從區塊鏈實時獲取),并且非常適合像PySpark這樣的分布式處理框架。
這樣我們就更容易理解了。
該調用是對名為swapexacttokensfortokens的方法的調用,用戶正在放入25億單位的起始代幣,并期望至少返回194,024,196,127,819,599,854,524,737單位的目標代幣。這些數字看起來可能是天文數字,但請記住,代幣單位通常用1/10^n表示,其中n大約是18。N有時被稱為代幣的十進制值。該path數組描述了在此交易中交換的代幣。每個數組元素都是代幣合約的地址。第一個是USDC(一種與美元掛鉤的穩定幣),第二個是WrappedEth(帶有ERC20接口的以太坊),第三個是DXO(一種深空游戲貨幣)。將1和2放在一起,我們可以推斷用戶請求交換2,500USDC(USDC的十進制值為6)和大約1.94億DXO(DXO的十進制值為18)。由于這種特殊的成對交換不能直接獲得,交易將通過WETH的中間代幣進行調解。解碼日志
該交易在執行過程中還觸發了7個事件,可以通過logs在以太坊上查詢Google的PublicDataset中的表獲得,也可以通過Etherscan查看。與用戶所要求的交換相對應的兩個最顯著的記錄是:
log_index:47transaction_hash:0x87a3bc85da972583e22da329aa109ea0db57c54a2eee359b2ed12597f5cb1a64transaction_index:37?address:0xb4e16d0168e52d35cacd2c6185b44281ec28c9dcdata:0x000000000000000000000000000000000000000000000000000000009502f90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000093f8f932b016b1ctopics:?block_timestamp:2021-10-1900:00:18block_number:13444845block_hash:0xe9ea4fc0ef9a13b1e403e68e3ff94bc94e472132528fe8f07ade422b84a43afc
還有
log_index:50transaction_hash:0x87a3bc85da972583e22da329aa109ea0db57c54a2eee359b2ed12597f5cb1a64transaction_index:37?address:0x242301fa62f0de9e3842a5fb4c0cdca67e3a2fabdata:0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000093f8f932b016b1c000000000000000000000000000000000000000000a137bb41b9113069a51e190000000000000000000000000000000000000000000000000000000000000000topics:?block_timestamp:2021-10-1900:00:18block_number:13444845block_hash:0xe9ea4fc0ef9a13b1e403e68e3ff94bc94e472132528fe8f07ade422b84a43afc
同樣,相關詳細信息在topics和data字段中編碼為十六進制字符串。與transaction的情況一樣,input瀏覽這些數據字段的結構是有益的。topics是一個數組,其中第一個元素表示事件接口定義的哈希簽名。topics數組中的任何其他元素通常是事件中涉及的區塊鏈地址,根據具體上下文可能存在,也可能不存在。data表示事件參數值,其長度根據事件定義而不同。與交易的情況一樣,我們需要引用合約ABI,以便將其轉換為人類可讀的形式。
幣情觀察室 | 我是如何從650賺到100個比特幣的?:4月8日 19:00,金色盤面邀請實盤大V 幣圈棟哥做客金色財經《幣情觀察室》直播間,將分享《我是如何從650賺到100個比特幣的?》,敬請關注,掃描下圖二維碼即可觀看直播![2020/4/8]
敏銳的讀者會注意到上面日志中的合約地址0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc和0x242301fa62f0de9e3842a5fb4c0cdca67e3a2fab與用戶EOA最初調用的Routerv2合約0x7a250d5630b4cf539739df2c5dacb4c659f2488d不同。這兩個地址對應USDC-WETH和DXO-WETH代幣對的Uniswapv2對合約。這些合約負責持有各自交易對的流動性,并實際進行交換。用戶最初與之交互的Router合約作為一個協調器,并向適當的配對合約發起內部交易(跟蹤)。因此,為了解碼這些事件,我們還需要一對合約ABI。解碼日志示例如下:
fromweb3._utils.eventsimportget_event_datareturntopic2abievent_abi=topic2abi]evt_name=event_abidata=get_event_data(w3.codec,event_abi,log)target_schema=event_abidecoded_data=convert_to_hex(data,target_schema)return(evt_name,json.dumps(decoded_data),json.dumps(target_schema))exceptException:return('decodeerror',traceback.format_exc(),None)else:return('nomatchingabi',None,None)pair_abi=',"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":,"name":"Approval","type":"event"},{"anonymous":false,"inputs":,"name":"Burn","type":"event"},{"anonymous":false,"inputs":,"name":"Mint","type":"event"},{"anonymous":false,"inputs":,"name":"Swap","type":"event"},{"anonymous":false,"inputs":,"name":"Sync","type":"event"},{"anonymous":false,"inputs":,"name":"Transfer","type":"event"},{"constant":true,"inputs":,"name":"DOMAIN_SEPARATOR","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":,"name":"MINIMUM_LIQUIDITY","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":,"name":"PERMIT_TYPEHASH","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":,"name":"allowance","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":,"name":"approve","outputs":,"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":,"name":"balanceOf","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":,"name":"burn","outputs":,"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":,"name":"decimals","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":,"name":"factory","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":,"name":"getReserves","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":,"name":"initialize","outputs":,"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":,"name":"kLast","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":,"name":"mint","outputs":,"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":,"name":"name","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":,"name":"nonces","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":,"name":"permit","outputs":,"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":,"name":"price0CumulativeLast","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":,"name":"price1CumulativeLast","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":,"name":"skim","outputs":,"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":,"name":"swap","outputs":,"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":,"name":"symbol","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":,"name":"sync","outputs":,"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":,"name":"token0","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":,"name":"token1","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":,"name":"totalSupply","outputs":,"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":,"name":"transfer","outputs":,"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":,"name":"transferFrom","outputs":,"payable":false,"stateMutability":"nonpayable","type":"function"}]'output=decode_log('0x000000000000000000000000000000000000000000000000000000009502f90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000093f8f932b016b1c',,pair_abi)print('eventemitted:',output)print('arguments:',json.dumps(json.loads(output),indent=2))
動態 | 200余名全球執法人員參加國際犯罪會議,探討如何制止加密犯罪:據TheNextWeb報道,本周,根據澳大利亞聯邦警察(AFP)的聲明,超過200名來自世界各地的執法人員將出席在布里斯班舉行的國際犯罪會議,共同探討尋找加密犯罪的方法。AFP代理局長Justine Gough表示,加密貨幣和加密通信等技術的進步已經改變了罪犯獲取和隱藏資產的方式,抓住并消除犯罪阻止他們獲利,是打擊有組織的犯罪網絡最有效的方法之一。[2019/11/14]
與交易解碼的代碼類似,示例代碼針對批量解碼用例進行了優化,并與類似PySpark的東西一起使用,以處理大量日志事件。運行以上收益率:
eventemitted:Swaparguments:{"sender":"0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D","to":"0x242301FA62f0De9e3842A5Fb4c0CdCa67e3A2Fab","amount0In":2500000000,"amount1In":0,"amount0Out":0,"amount1Out":666409132118600476}
還有
eventemitted:Swaparguments:{"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這樣的區塊瀏覽器上檢查數據消耗以及閱讀智能合約源代碼的組合來實現。這是制定正確的解碼和分析策略的關鍵條件。
Source:https://towardsdatascience.com/decoding-ethereum-smart-contract-data-eed513a65f76
聲音 | 薛蠻子:行業應重點關注如何建立信任機制:著名天使投資人、UT斯達康創始人薛蠻子在“重構新生態”2018全球第五屆區塊鏈技術應用論壇上,就區塊鏈投資提到:很多散戶依靠對百倍千倍的幻想而去投資數字貨幣是非常危險的事。同時就區塊鏈監管也提到:如何在倒“洗澡水”的時候怎么又不把“澡盆里的孩子”倒出去,這是個很有技術難度的事情,也是短時間內很難實現的事。個人認為:接下來行業內胡亂“割韭菜”行為肯定行不通了,如何建立信任機制才是行業內應該去做的事情。[2018/7/26]
在美國眾議院聽證會喬治城大學法學教授表示:監管的重點應該在于數字代幣如何被對待:在美國眾議院金融服務委員會《檢查加密貨幣和ICO市場》的聽證會上,喬治城大學法學教授Chris Brummer博士表示,ICO將會成為區塊鏈行業的主要融資方式,但監管的重點應該在于數字代幣如何被對待,以及系統如何被監管。他還表示,許多ICO欺詐非常明顯,需要監管機構介入,更新法律法規,并且提供ICO白皮書指導。[2018/3/14]
Tags:PUTTYPETYPUTSBitconch Reputation Heattype幣解鎖NEXTYPEDeutsche eMark
原標題:《育碧入場,a16z和FTX加緊布局的鏈游賽道里,還有哪些熱門的游戲平臺》近年來,游戲市場呈現出不斷增長的態勢,加上新冠疫情的影響進一步提高了用戶對游戲娛樂的參與度.
1900/1/1 0:00:00據Cointelegraph10月30日報道,在由加密經紀公司VoyagerDigital贊助的NBA挑戰活動中,達拉斯獨行俠隊的一名球迷在連續投籃后贏得了10萬美元的比特幣.
1900/1/1 0:00:00據浙江數字經濟公眾號消息,11月12日下午,浙江省經信廳組織召開了“元宇宙”產業發展座談會。省經信廳數字經濟處姚春彬,省虛擬現實產業聯盟理事長、浙江大學教授金小剛,北航VR/AR創新研究院常務副.
1900/1/1 0:00:00北京時間10月9日早上8點,以太坊域名系統治理代幣正式開放空投申領,毫無疑問,再次成為加密歷史上又一場龐大的空投福利.
1900/1/1 0:00:0010月30日,CoinDesk發表分析文章《Facebook以其荒謬的更名再次竊取加密創意》。文章稱,馬克·扎克伯格關于元宇宙的愿景與區塊鏈行業首次提出的開放、可互操作的愿景幾乎沒有關系.
1900/1/1 0:00:00原標題:《Web3世界中創作者經濟的痛點與機遇》律動研究院在上篇分享的《現在是加入Web3創作者經濟的最佳時機》中詳述了Web3.0是如何完全釋放創作者經濟潛力的底層邏輯.
1900/1/1 0:00:00