如何解码以太坊智能合约数据,并批量处理相关细节?_UNI:hotcs币什么价格

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

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

美国国会法案呼吁联邦政府研究加密货币用于非法活动的案例,并就如何减少这些用途提出建议:4月27日消息,周四向美国参议院和众议院提交的一项两党法案将呼吁联邦政府研究加密货币用于非法活动的案例,并就如何减少这些用途提出建议。《金融技术保护法案》建议成立一个工作组,负责研究恐怖分子或其他犯罪分子如何使用加密货币和其他新的金融技术,并为国会和监管机构提出旨在打击这些用途的建议。[2023/4/27 14:31:26]

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

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

Stargate DAO成员在社区会议上讨论如何处理即将收到的160万枚ARB:3月30日消息,Stargate DAO成员在周三社区电话会议上讨论如何处理160万枚Arbitrum(ARB)代币的预期分配,这些代币价值不到200万美元。LayerZero Labs的员工MaxPower表示,这些代币尚未收到,但当收到时将必须决定是否持有、出售、部署或委托这些代币。

一些与会者建议,DAO应该将ARB代币分发给用户,或将其部署为流动性激励。与此同时,其他治理代币持有者建议委托ARB代币,以便Stargate DAO可以参与Arbitrum治理。

据DeFiLlama的数据,Stargate的总锁定价值(TVL)为3.64亿美元,其中近22%来自Arbitrum平台。(CoinDesk)[2023/3/30 13:34:35]

同样,相关详细信息在topics和data字段中编码为十六进制字符串。与transaction的情况一样,input浏览这些数据字段的结构是有益的。topics是一个数组,其中第一个元素表示事件接口定义的哈希签名。topics数组中的任何其他元素通常是事件中涉及的区块链地址,根据具体上下文可能存在,也可能不存在。data表示事件参数值,其长度根据事件定义而不同。与交易的情况一样,我们需要引用合约ABI,以便将其转换为人类可读的形式。

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

李礼辉:如何进行必要的数字金融制度建设等问题值得关注:12月31日,由清华大学经济管理学院数字金融资产研究中心主办的“数字金融:创新、发展与监管”高端研讨会中,中国银行原行长李礼辉表示,如何能满足适用于我国规模化可靠应用的需求、如何进行必要的数字金融制度的建设、负责数字人民币技术架构的研发、维护、运行等方面工作的机构体制如何设立及如何探索我国主导的全球化数字货币的可行路径是值得关注的重要问题。[2021/1/4 16:22:26]

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

动态 | 火币中国CEO与马来西亚总理讨论区块链将如何在马来西亚落地:据雅虎财经消息,近日,火币中国CEO袁煜明与马来西亚总理马哈蒂尔(Mahathir Mohamad)就“如何在制造业和能源行业中应用区块链”以及“区块链将如何在马来西亚落地”进行了讨论。[2019/5/29]

首席税务研究分析师:“空投”和“硬分叉”如何纳税目前仍悬而未决:据cnbc消息,税务研究所首席税务研究分析师Nathan Rigney表示确定“空投”和“硬分叉”的税额目前是一个悬而未决的问题,但是这可能与股息更相似。此外cnbc文章还表明,如果纳税人通过“挖矿”流程获得了比特币或其他加密货币,国税局通常情况下认为应纳税利润为自营职业收入。由于国税局将比特币视为财产,因此加密货币的网上交易需缴纳资本利得税。[2018/4/14]

郑重声明: 本文版权归原作者所有, 转载文章仅为传播更多信息之目的, 如作者信息标记有误, 请第一时间联系我们修改或删除, 多谢。

金宝趣谈

[0:15ms0-7:101ms