diff --git a/src/TxBrowser.js b/src/TxBrowser.js index 1c4abdf5a5..d950428c7e 100644 --- a/src/TxBrowser.js +++ b/src/TxBrowser.js @@ -10,7 +10,7 @@ function TxBrowser (_web3) { this.web3 = _web3 this.blockNumber - this.txNumber = '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51' + this.txNumber = '0x71a6d583d16d142c5c3e8903060e8a4ee5a5016348a9448df6c3e63b68076ec4' this.hash this.from this.to diff --git a/src/trace/traceAnalyser.js b/src/trace/traceAnalyser.js index b482ae86d3..897bd6b8a4 100644 --- a/src/trace/traceAnalyser.js +++ b/src/trace/traceAnalyser.js @@ -21,20 +21,40 @@ TraceAnalyser.prototype.analyse = function (trace, tx, callback) { if (traceHelper.isContractCreation(tx.to)) { this.traceCache.pushContractCreation(tx.to, tx.input) } + this.buildCalldata(0, this.trace[0], tx, true) for (var k = 0; k < this.trace.length; k++) { var step = this.trace[k] - this.buildCalldata(k, step) this.buildMemory(k, step) - this.buildDepth(k, step, callStack) + this.buildDepth(k, step, tx, callStack) context = this.buildStorage(k, step, context) } callback(null, true) } -TraceAnalyser.prototype.buildCalldata = function (index, step) { - if (step.calldata) { - this.traceCache.pushCallDataChanges(index) +TraceAnalyser.prototype.buildCalldata = function (index, step, tx, newContext) { + var calldata = '' + if (index === 0) { + calldata = tx.input + this.traceCache.pushCallDataChanges(index, calldata) + } else if (!newContext) { + var lastCall = this.traceCache.callsData[this.traceCache.callDataChanges[this.traceCache.callDataChanges.length - 2]] + this.traceCache.pushCallDataChanges(index + 1, lastCall) + } else { + var memory = this.trace[this.traceCache.memoryChanges[this.traceCache.memoryChanges.length - 1]].memory + var callStep = this.trace[index] + var stack = callStep.stack + var offset = '' + var size = '' + if (callStep.op === 'DELEGATECALL') { + offset = 2 * parseInt(stack[stack.length - 3], 16) + size = 2 * parseInt(stack[stack.length - 4], 16) + } else { + offset = 2 * parseInt(stack[stack.length - 4], 16) + size = 2 * parseInt(stack[stack.length - 5], 16) + } + calldata = '0x' + memory.join('').substr(offset, size) + this.traceCache.pushCallDataChanges(index + 1, calldata) } } @@ -62,7 +82,7 @@ TraceAnalyser.prototype.buildStorage = function (index, step, context) { return context } -TraceAnalyser.prototype.buildDepth = function (index, step, callStack) { +TraceAnalyser.prototype.buildDepth = function (index, step, tx, callStack) { if (traceHelper.isCallInstruction(step) && !traceHelper.isCallToPrecompiledContract(index, this.trace)) { if (traceHelper.isCreateInstruction(step)) { var contractToken = traceHelper.contractCreationToken(index) @@ -81,12 +101,16 @@ TraceAnalyser.prototype.buildDepth = function (index, step, callStack) { this.traceCache.pushCallStack(index + 1, { callStack: callStack.slice(0) }) + this.buildCalldata(index, step, tx, true) } else if (traceHelper.isReturnInstruction(step)) { - callStack.pop() - this.traceCache.pushCallChanges(step, index + 1) - this.traceCache.pushCallStack(index + 1, { - callStack: callStack.slice(0) - }) + if (index + 1 < this.trace.length) { + callStack.pop() + this.traceCache.pushCallChanges(step, index + 1) + this.traceCache.pushCallStack(index + 1, { + callStack: callStack.slice(0) + }) + this.buildCalldata(index, step, tx, false) + } } } diff --git a/src/trace/traceCache.js b/src/trace/traceCache.js index cce6d201a6..4942baf739 100644 --- a/src/trace/traceCache.js +++ b/src/trace/traceCache.js @@ -9,6 +9,7 @@ TraceCache.prototype.init = function () { this.callChanges = [] this.returnChanges = [] this.calls = {} + this.callsData = {} this.contractCreation = {} this.callDataChanges = [] @@ -18,8 +19,9 @@ TraceCache.prototype.init = function () { this.callStack = {} // contains all callStack by vmtrace index (we need to rebuild it, callstack is not included in the vmtrace) } -TraceCache.prototype.pushCallDataChanges = function (value) { +TraceCache.prototype.pushCallDataChanges = function (value, calldata) { this.callDataChanges.push(value) + this.callsData[value] = calldata } TraceCache.prototype.pushMemoryChanges = function (value) { diff --git a/src/trace/traceManager.js b/src/trace/traceManager.js index b7ab9a32bf..fb4c5be94e 100644 --- a/src/trace/traceManager.js +++ b/src/trace/traceManager.js @@ -101,7 +101,7 @@ TraceManager.prototype.getCallDataAt = function (stepIndex, callback) { } var callDataChange = traceHelper.findLowerBound(stepIndex, this.traceCache.callDataChanges) if (callDataChange === undefined) return callback('no calldata found', null) - callback(null, [this.trace[callDataChange].calldata]) + callback(null, [this.traceCache.callsData[callDataChange]]) } TraceManager.prototype.getCallStackAt = function (stepIndex, callback) {