diff --git a/libs/remix-debug/src/solidity-decoder/internalCallTree.ts b/libs/remix-debug/src/solidity-decoder/internalCallTree.ts index 8271c4b1a5..4a815e25ab 100644 --- a/libs/remix-debug/src/solidity-decoder/internalCallTree.ts +++ b/libs/remix-debug/src/solidity-decoder/internalCallTree.ts @@ -42,6 +42,10 @@ export class InternalCallTree { } gasCostPerLine offsetToLineColumnConverter + pendingConstructorExecutionAt: number + pendingConstructorId: number + pendingConstructor + constructorsStartExecution /** * constructor @@ -109,6 +113,10 @@ export class InternalCallTree { this.astWalker = new AstWalker() this.reducedTrace = [] this.locationAndOpcodePerVMTraceIndex = {} + this.pendingConstructorExecutionAt = -1 + this.pendingConstructorId = -1 + this.constructorsStartExecution = {} + this.pendingConstructor = null } /** @@ -192,7 +200,7 @@ export class InternalCallTree { } } -async function buildTree (tree, step, scopeId, isCreation, functionDefinition?, contractObj?, sourceLocation?) { +async function buildTree (tree, step, scopeId, isCreation, functionDefinition?, contractObj?, sourceLocation?, validSourceLocation?) { let subScope = 1 tree.scopeStarts[step] = scopeId tree.scopes[scopeId] = { firstStep: step, locals: {}, isCreation, gasCost: 0 } @@ -217,9 +225,9 @@ async function buildTree (tree, step, scopeId, isCreation, functionDefinition?, included.file === source.file) } - let currentSourceLocation = { start: -1, length: -1, file: -1, jump: '-' } + let currentSourceLocation = sourceLocation || { start: -1, length: -1, file: -1, jump: '-' } let previousSourceLocation = currentSourceLocation - let previousValidSourceLocation = currentSourceLocation + let previousValidSourceLocation = validSourceLocation || currentSourceLocation while (step < tree.traceManager.trace.length) { let sourceLocation let validSourceLocation @@ -275,15 +283,31 @@ async function buildTree (tree, step, scopeId, isCreation, functionDefinition?, const contractObj = await tree.solidityProxy.contractObjectAtAddress(address) const generatedSources = getGeneratedSources(tree, scopeId, contractObj) - const functionDefinition = resolveFunctionDefinition(tree, sourceLocation, generatedSources) + let functionDefinition = resolveFunctionDefinition(tree, sourceLocation, generatedSources) const isInternalTxInstrn = isCallInstruction(stepDetail) const isCreateInstrn = isCreateInstruction(stepDetail) // we are checking if we are jumping in a new CALL or in an internal function - if (isInternalTxInstrn || (previousSourceLocation.jump === 'i' && functionDefinition)) { + + const constructorExecutionStarts = tree.pendingConstructorExecutionAt > -1 && tree.pendingConstructorExecutionAt < validSourceLocation.start + if (functionDefinition && functionDefinition.kind === 'constructor' && tree.pendingConstructorExecutionAt === -1 && !tree.constructorsStartExecution[functionDefinition.id]) { + tree.pendingConstructorExecutionAt = validSourceLocation.start + tree.pendingConstructorId = functionDefinition.id + tree.pendingConstructor = functionDefinition + // from now on we'll be waiting for a change in the source location which will mark the beginning of the constructor execution. + // constructorsStartExecution allows to keep track on which constructor has already been executed. + } + if (constructorExecutionStarts || isInternalTxInstrn || (functionDefinition && previousSourceLocation.jump === 'i')) { try { + if (constructorExecutionStarts) { + tree.constructorsStartExecution[tree.pendingConstructorId] = tree.pendingConstructorExecutionAt + functionDefinition = tree.pendingConstructor + tree.pendingConstructorExecutionAt = -1 + tree.pendingConstructorId = -1 + tree.pendingConstructor = null + } const newScopeId = scopeId === '' ? subScope.toString() : scopeId + '.' + subScope - const externalCallResult = await buildTree(tree, step, newScopeId, isCreateInstrn, functionDefinition, contractObj, sourceLocation) + const externalCallResult = await buildTree(tree, step, newScopeId, isCreateInstrn, functionDefinition, contractObj, sourceLocation, validSourceLocation) if (externalCallResult.error) { return { outStep: step, error: 'InternalCallTree - ' + externalCallResult.error } } else { @@ -328,7 +352,6 @@ async function registerFunctionParameters (tree, functionDefinition, step, scope const functionDefinitionAndInputs = { functionDefinition, inputs: [] } // means: the previous location was a function definition && JUMPDEST // => we are at the beginning of the function and input/output are setup - try { const stack = tree.traceManager.getStackAt(step) const states = tree.solidityProxy.extractStatesDefinitions()