从Geth的debug_traceCall交易追踪中同时提取日志与存储的方法问询
从Geth debug_traceCall中同时提取事件日志与存储操作的修改方案
要在原有代码基础上同时提取事件(LOG指令)和存储操作(SLOAD/SSTORE指令),需要执行以下操作:
核心修改点
- 新增存储操作检测逻辑:在
step函数中添加对SLOAD、SSTORE两种存储相关操作码的判断 - 提取存储操作关键数据:针对不同存储指令,从栈或合约存储中提取键、值信息
- 统一结果格式:给每条记录添加类型标识,区分是事件日志还是存储操作
修改后的完整代码
{ data: [], fault: function (log) { }, step: function (log) { // 保留原有事件日志提取逻辑,新增类型标识 const topicCountMatch = log.op.toString().match(/LOG(\d)/); if (topicCountMatch) { const topicCount = topicCountMatch[1]; const logEntry = { type: 'log', address: log.contract.getAddress(), data: log.memory.slice(parseInt(log.stack.peek(0)), parseInt(log.stack.peek(0)) + parseInt(log.stack.peek(1))), }; for (let i = 0; i < topicCount; i++) { logEntry[`topic${i}`] = log.stack.peek(i + 2); } this.data.push(logEntry); } // 新增:处理SLOAD/SSTORE存储操作 const opName = log.op.toString(); if (opName === 'SLOAD' || opName === 'SSTORE') { const key = log.stack.peek(0); let value; if (opName === 'SSTORE') { // SSTORE:栈顶是存储键,下一个元素是要写入的值 value = log.stack.peek(1); } else { // SLOAD:从合约存储中读取对应键的当前值 value = log.contract.getStorage(key); } const storageEntry = { type: 'storage', address: log.contract.getAddress(), op: opName, key: key, value: value }; this.data.push(storageEntry); } }, result: function () { return this.data; } }
关键细节说明
- 操作码识别:通过
log.op.toString()判断当前执行的是LOGn、SLOAD还是SSTORE指令 - 栈元素读取:
stack.peek(n)从栈顶开始取值,0为栈顶元素,SSTORE的第二个参数(值)对应stack.peek(1) - 存储值获取:SLOAD需要通过
log.contract.getStorage(key)读取合约当前存储的实际值,而SSTORE直接从栈中获取要写入的值 - 结果区分:每条记录新增
type字段(log或storage),方便后续对事件和存储操作进行分类处理
内容的提问来源于stack exchange,提问作者MRW
相关产品推荐
相关产品推荐

