Skip to content

Commit c0b46dc

Browse files
ci-botyann300
authored andcommitted
fix nested function
1 parent 211c35c commit c0b46dc

File tree

2 files changed

+27
-11
lines changed

2 files changed

+27
-11
lines changed

libs/remix-debug/src/solidity-decoder/internalCallTree.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -676,10 +676,12 @@ async function buildTree (tree: InternalCallTree, step, scopeId, isCreation, fun
676676
let previousValidSourceLocation = validSourceLocation || currentSourceLocation
677677
let compilationResult: CompilerAbstract
678678
let currentAddress = ''
679+
let firstExecutionStep = true
679680
while (step < tree.traceManager.trace.length) {
680681
let sourceLocation
681682
let validSourceLocation
682683
let address
684+
let isInvalidSource = false
683685

684686
try {
685687
address = tree.traceManager.getCurrentCalledAddressAt(step)
@@ -696,7 +698,8 @@ async function buildTree (tree: InternalCallTree, step, scopeId, isCreation, fun
696698
}
697699
}
698700
const amountOfSources = tree.sourceLocationTracker.getTotalAmountOfSources(address, compilationResult.data.contracts)
699-
if (tree.sourceLocationTracker.isInvalidSourceLocation(currentSourceLocation, amountOfSources)) { // file is -1 or greater than amount of sources
701+
isInvalidSource = tree.sourceLocationTracker.isInvalidSourceLocation(currentSourceLocation, amountOfSources)
702+
if (isInvalidSource) { // file is -1 or greater than amount of sources
700703
validSourceLocation = previousValidSourceLocation
701704
} else
702705
validSourceLocation = currentSourceLocation
@@ -763,16 +766,19 @@ async function buildTree (tree: InternalCallTree, step, scopeId, isCreation, fun
763766
// check if there is a function at destination - but only for AST node resolution
764767
const contractObj = await tree.solidityProxy.contractObjectAtAddress(address)
765768
const generatedSources = getGeneratedSources(tree, scopeId, contractObj)
766-
const { nodes, blocksDefinition } = await resolveNodesAtSourceLocation(tree, sourceLocation, generatedSources, address)
767-
768-
functionDefinition = await resolveFunctionDefinition(tree, sourceLocation, generatedSources, address)
769+
const { nodes, blocksDefinition, functionDefinition } = await resolveNodesAtSourceLocation(tree, sourceLocation, generatedSources, address)
769770

770771
if (!tree.scopes[scopeId].functionDefinition && stepDetail.op === 'JUMPDEST' && functionDefinition && (tree.scopes[scopeId].firstStep === step - 1 || tree.scopes[scopeId].firstStep === step - 2)) {
771772
tree.scopes[scopeId].functionDefinition = functionDefinition
772773
tree.scopes[scopeId].lowLevelScope = false
773774
await registerFunctionParameters(tree, functionDefinition, step - 1, scopeId, contractObj, previousSourceLocation, address)
774775
}
775776

777+
// if the first step of the execution leads to invalid source (generated code), we consider it a low level scope.
778+
if (firstExecutionStep && isInvalidSource) {
779+
tree.scopes[scopeId].lowLevelScope = true
780+
}
781+
776782
// Update symbolic stack based on opcode execution
777783
const previousSymbolicStack = tree.symbolicStackManager.getStackAtStep(step)
778784
if (tree.debug && stepDetail.stack.length !== previousSymbolicStack.length) {
@@ -888,6 +894,7 @@ async function buildTree (tree: InternalCallTree, step, scopeId, isCreation, fun
888894
previousValidSourceLocation = validSourceLocation
889895
step++
890896
}
897+
if (firstExecutionStep) firstExecutionStep = false
891898
}
892899
return { outStep: step }
893900
}

libs/remix-debug/test/decoder/localsTests/parameterTypes.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import * as helper from './helper'
44
const { ethers } = require('ethers')
55

66
module.exports = async function (st, privateKey, contractBytecode, compilationResult, contractCode) {
7-
st.plan(26)
87
const enableCtorTest = false
98
// Test scenarios with expected parameter values
109
const testCases = [
@@ -53,11 +52,13 @@ module.exports = async function (st, privateKey, contractBytecode, compilationRe
5352
{
5453
name: 'create2Test',
5554
signature: 'create2Test(uint256,string,bytes32)',
56-
params: [555, 'Create2Test', '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'],
55+
params: [555, 'Create2Test', '0x1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF'],
5756
description: 'CREATE2 operation parameters'
5857
}
5958
]
6059

60+
st.plan((testCases.length * 3) + 2 + 2 + 1) // 2 Additional tests for internalCallTest + 2 Additional tests for thisCallTest + 1 Additional test for create2Test (salt param)
61+
6162
// Helper function to encode parameters
6263
function encodeParams(signature: string, params: any[]): string {
6364
// Use ethers interface to encode function call
@@ -68,7 +69,6 @@ module.exports = async function (st, privateKey, contractBytecode, compilationRe
6869

6970
// Helper function to find scope by function name and get its firstStep
7071
function findFunctionScope(nestedScopes: NestedScope[], functionName: string): { scope: NestedScope, firstStep: number } | null {
71-
let foundDuplicate = false // TODO this needs to be fixed, there are always 2 nodes for a single function call
7272
function traverse(scope: NestedScope, parentFirstStep?: number): { scope: NestedScope, firstStep: number } | null {
7373
// Check if this scope matches our function
7474
if (scope.functionDefinition?.name === functionName || scope.functionDefinition?.kind === functionName) {
@@ -80,8 +80,7 @@ module.exports = async function (st, privateKey, contractBytecode, compilationRe
8080
if (scope.children) {
8181
for (const child of scope.children) {
8282
const result = traverse(child, scope.firstStep || parentFirstStep)
83-
if (result && foundDuplicate) return result
84-
if (result) foundDuplicate = true
83+
if (result) return result
8584
}
8685
}
8786

@@ -108,7 +107,7 @@ module.exports = async function (st, privateKey, contractBytecode, compilationRe
108107
await helper.setupDebugger(privateKey, deployBytecode, compilationResult, contractCode)
109108

110109
const { scopes: deployScopes, scopeStarts: deployScopeStarts } = await waitForDeployCallTree()
111-
const deployNestedScopes: NestedScope[] = deployCallTree.getScopesAsNestedJSON()
110+
const deployNestedScopes: NestedScope[] = deployCallTree.getScopesAsNestedJSON('nojump')
112111

113112
console.log(deployNestedScopes)
114113

@@ -165,7 +164,7 @@ module.exports = async function (st, privateKey, contractBytecode, compilationRe
165164
)
166165

167166
const { scopes, scopeStarts } = await waitForCallTree()
168-
const nestedScopes: NestedScope[] = callTree.getScopesAsNestedJSON()
167+
const nestedScopes: NestedScope[] = callTree.getScopesAsNestedJSON('nojump')
169168

170169
// Find the target function scope
171170
const functionScope = findFunctionScope(nestedScopes, testCase.name)
@@ -220,6 +219,16 @@ module.exports = async function (st, privateKey, contractBytecode, compilationRe
220219
}
221220
}
222221

222+
if (testCase.signature.includes('bytes32')) {
223+
const stringParamNames = ['_salt']
224+
const expectedBytes32Param = stringParamNames.find(name => locals[name])
225+
226+
if (expectedBytes32Param) {
227+
st.equals(locals[expectedBytes32Param].value, testCase.params[2],
228+
`${testCase.name}: bytes32 parameter should be decoded correctly`)
229+
}
230+
}
231+
223232
st.ok(Object.keys(locals).length > 0, `${testCase.name}: Should have decoded local variables`)
224233
})
225234

0 commit comments

Comments
 (0)