diff --git a/libs/remix-debug/src/solidity-decoder/internalCallTree.ts b/libs/remix-debug/src/solidity-decoder/internalCallTree.ts
index 4233ec9cbb..4f74ad4585 100644
--- a/libs/remix-debug/src/solidity-decoder/internalCallTree.ts
+++ b/libs/remix-debug/src/solidity-decoder/internalCallTree.ts
@@ -165,7 +165,6 @@ export class InternalCallTree {
const scope = this.findScope(vmtraceIndex)
if (!scope) return []
let scopeId = this.scopeStarts[scope.firstStep]
- const scopeDetail = this.scopes[scopeId]
const functions = []
if (!scopeId) return functions
let i = 0
@@ -174,6 +173,7 @@ export class InternalCallTree {
i += 1
if (i > 1000) throw new Error('retrieFunctionStack: recursion too deep')
const functionDefinition = this.functionDefinitionsByScope[scopeId]
+ const scopeDetail = this.scopes[scopeId]
if (functionDefinition !== undefined) {
functions.push({ ...functionDefinition, ...scopeDetail })
}
@@ -280,7 +280,10 @@ async function buildTree (tree, step, scopeId, isCreation, functionDefinition?,
const stepDetail: StepDetail = tree.traceManager.trace[step]
const nextStepDetail: StepDetail = tree.traceManager.trace[step + 1]
if (stepDetail && nextStepDetail) {
+ // for complicated opcodes which don't have a static gas cost:
stepDetail.gasCost = parseInt(stepDetail.gas as string) - parseInt(nextStepDetail.gas as string)
+ } else {
+ stepDetail.gasCost = parseInt(stepDetail.gasCost as unknown as string)
}
// gas per line
diff --git a/libs/remix-debug/test/decoder/localsTests/int.ts b/libs/remix-debug/test/decoder/localsTests/int.ts
index 53f0e11978..fa52b55714 100644
--- a/libs/remix-debug/test/decoder/localsTests/int.ts
+++ b/libs/remix-debug/test/decoder/localsTests/int.ts
@@ -61,6 +61,11 @@ module.exports = function (st, privateKey, contractBytecode, compilationResult,
st.equals(functions3.length, 1)
st.equal(functions1[0].gasCost, 54)
+ st.equal(functions1[1].gasCost, 436)
+
+ st.equal(functions2[0].gasCost, 23)
+ st.equal(functions2[1].gasCost, 54)
+ st.equal(functions2[2].gasCost, 436)
st.equals(Object.keys(functions1[0])[0], 'functionDefinition')
st.equals(Object.keys(functions1[0])[1], 'inputs')
diff --git a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.css b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.css
index 1a5e4926a9..01754f6ca3 100644
--- a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.css
+++ b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.css
@@ -20,4 +20,7 @@
.debuggerPanels {
overflow-y: auto;
height: fit-content;
+}
+.jumpToFunctionClick span {
+ cursor: pointer;
}
\ No newline at end of file
diff --git a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
index 73333e01a5..6ea35adb1c 100644
--- a/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
+++ b/libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
@@ -461,7 +461,7 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
{state.debugging && }
- {state.debugging &&
}
+ {state.debugging &&
}
{state.debugging && (
{
extractFunc,
formatSelfFunc,
registerEvent,
+ handleExpandFunc,
+ formatClassNamesFunc,
triggerEvent,
loadMoreEvent,
loadMoreCompletedEvent,
@@ -135,9 +137,9 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
toggleDropdown: !prevState.toggleDropdown
}
})
- }
+ };
- const handleExpand = (keyPath) => {
+ const handleExpand = handleExpandFunc || function (keyPath) {
if (!state.expandPath.includes(keyPath)) {
state.expandPath.push(keyPath)
} else {
@@ -221,6 +223,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
label={formatSelfFunc ? formatSelfFunc(key, data) : formatSelfDefault(key, data)}
onClick={() => handleExpand(keyPath)}
expand={state.expandPath.includes(keyPath)}
+ labelClass={formatClassNamesFunc && formatClassNamesFunc(key, data)}
>
{children}
@@ -246,6 +249,7 @@ export const DropdownPanel = (props: DropdownPanelProps) => {
label={formatSelfFunc ? formatSelfFunc(key, data) : formatSelfDefault(key, data)}
onClick={() => handleExpand(keyPath)}
expand={state.expandPath.includes(keyPath)}
+ labelClass={formatClassNamesFunc && formatClassNamesFunc(key, data)}
/>
)
}
diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/function-panel.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/function-panel.tsx
index 6450536f5a..d2106977ed 100644
--- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/function-panel.tsx
+++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/function-panel.tsx
@@ -2,16 +2,31 @@ import React, {useState, useEffect} from 'react' // eslint-disable-line
import DropdownPanel from './dropdown-panel' // eslint-disable-line
import {default as deepequal} from 'deep-equal' // eslint-disable-line
-export const FunctionPanel = ({data, className}) => {
- const [calldata, setCalldata] = useState(null)
+export const FunctionPanel = ({data, className, stepManager}) => {
+ const [functionData, setFunctionData] = useState(null)
useEffect(() => {
- if (!deepequal(calldata, data)) setCalldata(data)
+ if (!deepequal(functionData, data)) {
+ setFunctionData(data.map(el => el.label))
+ }
}, [data])
+ const formatSelfFunc = (key, data) => {
+ return data.self
+ }
+
+ const handleExpandFunc = (keyPath) => {
+ stepManager.jumpTo(data[parseInt(keyPath)].function.firstStep)
+ }
+
+ const formatClassNamesFunc = (keyPath, data) => {
+ return 'jumpToFunctionClick'
+ }
+
return (
+
-
+
)
}
diff --git a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger-head.tsx b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger-head.tsx
index 67ae5677fe..035d5f619a 100644
--- a/libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger-head.tsx
+++ b/libs/remix-ui/debugger-ui/src/lib/vm-debugger/vm-debugger-head.tsx
@@ -5,7 +5,7 @@ import StepDetail from './step-detail' // eslint-disable-line
import SolidityState from './solidity-state' // eslint-disable-line
import SolidityLocals from './solidity-locals' // eslint-disable-line
-export const VmDebuggerHead = ({vmDebugger: {registerEvent, triggerEvent}, debugging}) => {
+export const VmDebuggerHead = ({vmDebugger: {registerEvent, triggerEvent}, debugging, stepManager}) => {
const [functionPanel, setFunctionPanel] = useState(null)
const [stepDetail, setStepDetail] = useState({
'vm trace step': '-',
@@ -32,7 +32,11 @@ export const VmDebuggerHead = ({vmDebugger: {registerEvent, triggerEvent}, debug
const functions = []
for (const func of stack) {
- functions.push((func.functionDefinition.name || func.functionDefinition.kind) + '(' + func.inputs.join(', ') + ')' + ' - ' + func.gasCost + ' gas')
+ const label = (func.functionDefinition.name || func.functionDefinition.kind) + '(' + func.inputs.join(', ') + ')' + ' - ' + func.gasCost + ' gas'
+ functions.push({
+ label,
+ function: func
+ })
}
setFunctionPanel(() => functions)
})
@@ -127,7 +131,7 @@ export const VmDebuggerHead = ({vmDebugger: {registerEvent, triggerEvent}, debug
return (
-
+
diff --git a/libs/remix-ui/debugger-ui/src/types/index.ts b/libs/remix-ui/debugger-ui/src/types/index.ts
index a319e354be..a5893905e7 100644
--- a/libs/remix-ui/debugger-ui/src/types/index.ts
+++ b/libs/remix-ui/debugger-ui/src/types/index.ts
@@ -18,6 +18,8 @@ export type ExtractFunc = (json: any, parent?: any) => ExtractData
export type FormatSelfFunc = (key: string | number, data: ExtractData) => JSX.Element
export type RegisterEventType = (type: string, listener: any) => void // listener is a function
export type TriggerEventType = (type: string, payload: Array
) => void
+export type HandleExpandFunc = (keyPath: string) => void
+export type FormatClassNamesFunc = (key: string | number, data: ExtractData) => string
export interface DropdownPanelProps {
dropdownName: string,
className?: string,
@@ -30,6 +32,8 @@ export interface DropdownPanelProps {
extractFunc?: ExtractFunc,
formatSelfFunc?: FormatSelfFunc,
registerEvent?: RegisterEventType,
+ handleExpandFunc?: HandleExpandFunc,
+ formatClassNamesFunc?: FormatClassNamesFunc
triggerEvent?: TriggerEventType,
loadMoreEvent?: string,
loadMoreCompletedEvent?: string,