1 | # `remix-debug`
|
2 |
|
3 | remix-debug wrap other remix-* libraries and can be used to debug Ethereum transactions.
|
4 |
|
5 | + [Installation](#installation)
|
6 | + [Development](#development)
|
7 |
|
8 | ## Installation
|
9 |
|
10 |
|
11 | ```bash
|
12 | npm install remix-debug
|
13 | ```
|
14 |
|
15 | ## Development
|
16 |
|
17 | ```javascript
|
18 | var Debugger = require('remix-debug').EthDebugger
|
19 | var BreakpointManager = require('remix-debug').BreakpointManager
|
20 |
|
21 | var debugger = new Debugger({
|
22 | compilationResult: () => {
|
23 | return compilationResult // that helps resolving source location
|
24 | }
|
25 | })
|
26 |
|
27 | debugger.addProvider(web3, 'web3')
|
28 | debugger.switchProvider('web3')
|
29 |
|
30 | var breakPointManager = new remixCore.code.BreakpointManager(this.debugger, (sourceLocation) => {
|
31 | // return offsetToLineColumn
|
32 | })
|
33 | debugger.setBreakpointManager(breakPointManager)
|
34 | breakPointManager.add({fileName, row})
|
35 | breakPointManager.add({fileName, row})
|
36 |
|
37 | debugger.debug(<tx_hash>)
|
38 |
|
39 | // this.traceManager.getCurrentCalledAddressAt
|
40 |
|
41 | debugger.event.register('newTraceLoaded', () => {
|
42 | // start doing basic stuff like retrieving step details
|
43 | debugger.traceManager.getCallStackAt(34, (error, callstack) => {})
|
44 | })
|
45 |
|
46 | debugger.callTree.register('callTreeReady', () => {
|
47 | // start doing more complex stuff like resolvng local variables
|
48 | breakPointManager.jumpNextBreakpoint(true)
|
49 |
|
50 | var storageView = debugger.storageViewAt(38, <contract address>,
|
51 | storageView.storageSlot(0, (error, storage) => {})
|
52 | storageView.storageRange(error, storage) => {}) // retrieve 0 => 1000 slots
|
53 |
|
54 | debugger.extractStateAt(23, (error, state) => {
|
55 | debugger.decodeStateAt(23, state, (error, decodedState) => {})
|
56 | })
|
57 |
|
58 | debugger.sourceLocationFromVMTraceIndex(<contract address>, 23, (error, location) => {
|
59 | debugger.decodeLocalsAt(23, location, (error, decodedlocals) => {})
|
60 | })
|
61 |
|
62 | debugger.extractLocalsAt(23, (null, locals) => {})
|
63 |
|
64 | })
|
65 | ```
|
66 |
|
67 | ## Library
|
68 |
|
69 | Provides:
|
70 |
|
71 | ```javascript
|
72 | {
|
73 | code: {
|
74 | CodeManager: CodeManager,
|
75 | BreakpointManager: BreakpointManager
|
76 | },
|
77 | storage: {
|
78 | StorageViewer: StorageViewer,
|
79 | StorageResolver: StorageResolver
|
80 | },
|
81 | trace: {
|
82 | TraceManager: TraceManager
|
83 | }
|
84 | }
|
85 | ```
|
86 |
|
87 |
|
88 | TraceManager is a convenient way to access a VM Trace and resolve some value from it.
|
89 |
|
90 | `TraceManager()` :
|
91 |
|
92 | `function resolveTrace(stepIndex, tx)`
|
93 |
|
94 | `function init(stepIndex, tx)`
|
95 |
|
96 | `function inRange(stepIndex, tx)`
|
97 |
|
98 | `function isLoaded(stepIndex, tx)`
|
99 |
|
100 | `function getLength(stepIndex, tx)`
|
101 |
|
102 | `function accumulateStorageChanges(stepIndex, tx)`
|
103 |
|
104 | `function getAddresses(stepIndex, tx)`
|
105 |
|
106 | `function getCallDataAt(stepIndex, tx)`
|
107 |
|
108 | `function getCallStackAt(stepIndex, tx)`
|
109 |
|
110 | `function getStackAt(stepIndex, tx)`
|
111 |
|
112 | `function getLastCallChangeSince(stepIndex, tx)`
|
113 |
|
114 | `function getCurrentCalledAddressAt(stepIndex, tx)`
|
115 |
|
116 | `function getContractCreationCode(stepIndex, tx)`
|
117 |
|
118 | `function getMemoryAt(stepIndex, tx)`
|
119 |
|
120 | `function getCurrentPC(stepIndex, tx)`
|
121 |
|
122 | `function getReturnValue(stepIndex, tx)`
|
123 |
|
124 | `function getCurrentStep(stepIndex, tx)`
|
125 |
|
126 | `function getMemExpand(stepIndex, tx)`
|
127 |
|
128 | `function getStepCost(stepIndex, tx)`
|
129 |
|
130 | `function getRemainingGas(stepIndex, tx)`
|
131 |
|
132 | `function getStepCost(stepIndex, tx)`
|
133 |
|
134 | `function isCreationStep(stepIndex, tx)`
|
135 |
|
136 | `function findStepOverBack(stepIndex, tx)`
|
137 |
|
138 | `function findStepOverForward(stepIndex, tx)`
|
139 |
|
140 | `function findStepOverBack(stepIndex, tx)`
|
141 |
|
142 | `function findNextCall(stepIndex, tx)`
|
143 |
|
144 | `function findStepOut(stepIndex, tx)`
|
145 |
|
146 | `function checkRequestedStep(stepIndex, tx)`
|
147 |
|
148 | `function waterfall(stepIndex, tx)`
|
149 |
|
150 |
|
151 | - - - -
|
152 |
|
153 | `CodeManager(_traceManager)` :
|
154 |
|
155 | `function getCode(stepIndex, tx)` :
|
156 | Resolve the code of the given @arg stepIndex and trigger appropriate event
|
157 |
|
158 | `function resolveStep(address, cb)` :
|
159 | Retrieve the code located at the given @arg address
|
160 |
|
161 | `function getFunctionFromStep(stepIndex, sourceMap, ast)` :
|
162 | Retrieve the called function for the current vm step
|
163 |
|
164 | `function getInstructionIndex(address, step, callback)` :
|
165 | Retrieve the instruction index of the given @arg step
|
166 |
|
167 | `function getFunctionFromPC(address, pc, sourceMap, ast)` :
|
168 | Retrieve the called function for the given @arg pc and @arg address
|
169 |
|
170 | - - - -
|
171 |
|
172 | `BreakpointManager(_ethdebugger, _locationToRowConverter)` :
|
173 |
|
174 | `function jumpNextBreakpoint(defaultToLimit)` :
|
175 | start looking for the next breakpoint
|
176 |
|
177 | `function jumpPreviousBreakpoint(defaultToLimit)` :
|
178 | start looking for the previous breakpoint
|
179 |
|
180 | `function jump(direction, defaultToLimit)` :
|
181 | start looking for the previous or next breakpoint
|
182 |
|
183 | `function hasBreakpointAtLine((fileIndex, line)` :
|
184 | check the given pair fileIndex/line against registered breakpoints
|
185 |
|
186 | `function hasBreakpoint()` :
|
187 | return true if current manager has breakpoint
|
188 |
|
189 | `function add(sourceLocation)` :
|
190 | add a new breakpoint to the manager
|
191 |
|
192 | `function remove(sourceLocation)` :
|
193 | remove a breakpoint from the manager
|
194 |
|
195 | - - - -
|
196 |
|
197 | `StorageViewer(_context, _storageResolver, _traceManager)` :
|
198 |
|
199 | `function storageRange(defaultToLimit)` :
|
200 | return the storage for the current context (address and vm trace index)
|
201 |
|
202 | `function storageSlot(defaultToLimit)` :
|
203 | return a slot value for the current context (address and vm trace index)
|
204 |
|
205 | `function isComplete(direction, defaultToLimit)` :
|
206 | return True if the storage at @arg address is complete
|
207 |
|
208 | `function initialMappingsLocation((fileIndex, line)` :
|
209 | return all the possible mappings locations for the current context (cached) do not return state changes during the current transaction
|
210 |
|
211 | `function mappingsLocation()` :
|
212 | return all the possible mappings locations for the current context (cached) and current mapping slot. returns state changes during the current transaction
|
213 |
|
214 | `function extractMappingsLocationChanges(sourceLocation)` :
|
215 | retrieve mapping location changes from the storage changes.
|
216 |
|
217 | - - - -
|
218 |
|
219 | `StorageResolver()` :
|
220 |
|
221 | `function storageRange(tx, stepIndex, address, callback)` :
|
222 | return the storage for the current context (address and vm trace index)
|
223 |
|
224 | `function initialPreimagesMappings(tx, stepIndex, address, callback)` :
|
225 | return a slot value for the current context (address and vm trace index)
|
226 |
|
227 | `function storageSlot(slot, tx, stepIndex, address, callback)` :
|
228 | return True if the storage at @arg address is complete
|
229 |
|
230 | `function isComplete(address)` :
|
231 | return all the possible mappings locations for the current context (cached) do not return state changes during the current transaction
|
232 |
|