链资讯 链资讯
Ctrl+D收藏链资讯
首页 > BNB价格 > 正文

TYP:如何解码以太坊智能合约数据,并批量处理相关细节?_ALS

作者:

时间:

原标题:《解码以太坊智能合约数据》

正如我们在之前的文章中所讨论的,智能合约交易类似于智能合约驱动的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))

Lido将出版儿童读物《加密货币是如何运作的》:10月12日消息,流动性质押协议 Lido 宣布其团队将出版儿童读物《加密货币是如何运作的》,预印本已交付给以太坊创始人 Vitalik Buterin 审查。[2022/10/12 10:31:58]

在示例代码中有几点需要注意:

此代码设计用于批量处理大量交易。它假设数据已经存在于本地存储中(而不是从区块链实时获取),并且非常适合像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,以便将其转换为人类可读的形式。

直播 | 小凤仙 > 交易所如何助力矿业发展?:金色财经 · 直播主办的《 币圈 “后浪” 仙女直播周》第4期今晚20:00准时开始,本期“后浪”仙女Aex CMO 小凤仙将在直播间聊聊 “交易所如何助力矿业发展”,感兴趣的朋友扫码移步收听![2020/6/9]

敏锐的读者会注意到上面日志中的合约地址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))

动态 | 印度官员赴日本等国学习监管机构如何处理加密货币问题:据bitcoin 9月3日消息,印度证券交易委员会(SEBI)在其2017 – 18年度报告中透露,它已派出一些官员前往日本、英国、瑞士三个国家,研究监管机构如何处理加密货币问题。印度证券监管机构此次行动旨在与国际监管机构合作,深入了解其加密机制和系统,以改善其自身管理流程。[2018/9/3]

与交易解码的代码类似,示例代码针对批量解码用例进行了优化,并与类似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

韩国将于7日在国会召开‘虚拟货币制度化,该如何接近’研讨会:最近对虚拟货币的担忧和关注,虚拟货币相关学界及业界专家和政府核心相关人员将于韩国时间7日早上9点30分在韩国国会第二会议室中召开‘虚拟货币制度化,该如何接近’的研讨会。[2018/2/6]

芝加哥商品交易所集团就比特币期货将如何推出做了更为具体的解释:芝加哥商品交易所集团的股权产品负责人蒂姆-麦考特在接受外媒采访时表示:“交易所已经采取了保护措施,如更高的保证金水平、限制头寸和价格以抑制它即将推出的比特币期货的风险。”随后芝加哥商品交易所还阐述了三个层面的细节即交易、市场数据和双边市场的缺乏。[2017/12/3]

标签:TYPNAMEUTPALSTYPH价格NEO Name CreditUTP价格GALS

BNB价格热门资讯
ASS:Glassnode:比特币ETF推动CME BTC期货未平仓合约和交易量创新高_TNODE价格

巴比特讯,10月31日,据Glassnode最新链上周报,在首个比特币期货ETF推出的同时,比特币反弹至历史新高。长期持有者正在获取适度的利润,然而他们在下跌期间放缓了卖出速度.

STAT:英国加密初创企业Copper正计划筹集高达5亿美元资金_Wrapped Statera

据TheBlock10月20日消息,三位知情人士透露,英国加密初创企业Copper正在筹集高达5亿美元的资金。这笔投资将使Copper的估值超过10亿美元,使其成为独角兽.

TYP:观察 | 吉林省区块链专业资格评价标准条件摘录,区块链人才看过来!_ALS

金色财经报道,10月20日,吉林省人力资源和社会保障厅印发了《吉林省新职业职称评审实施意见》,其中包括新业态区块链专业技术资格评价基本标准条件.

加密货币:印尼主要伊斯兰教组织宣布加密货币“非法”_PLURA币

印度尼西亚最大的伊斯兰教组织之一NahdlatulUlama(NU)的东爪哇省分部发布了一项教令,认为加密货币的使用是伊斯兰法律禁止的.

PLU:巴比特晚间要闻一览_SAI

1.EricAdams赢得纽约市长竞选,此前称纽约市将成为“比特币中心”2.Meebits开放NFT三种新格式3D模型下载.

OPS:ProShares比特币期货ETF在两天内达到与加拿大ETF相同的资产净值_PRESALE币

据U.Today10月26日消息,据Kaiko称,ProShares比特币期货ETF已经突破了10亿美元的资产管理规模,并成为投资产品历史上最快实现这一目标的ETF.