sol-dbg 0.3.7 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/artifacts/helpers.d.ts +2 -3
- package/dist/artifacts/helpers.d.ts.map +1 -1
- package/dist/artifacts/helpers.js +45 -14
- package/dist/artifacts/helpers.js.map +1 -1
- package/dist/debug/abi.d.ts +10 -4
- package/dist/debug/abi.d.ts.map +1 -1
- package/dist/debug/abi.js +41 -11
- package/dist/debug/abi.js.map +1 -1
- package/dist/debug/artifact_manager.d.ts +9 -10
- package/dist/debug/artifact_manager.d.ts.map +1 -1
- package/dist/debug/artifact_manager.js +7 -6
- package/dist/debug/artifact_manager.js.map +1 -1
- package/dist/debug/decoding/calldata.d.ts.map +1 -1
- package/dist/debug/decoding/calldata.js +5 -6
- package/dist/debug/decoding/calldata.js.map +1 -1
- package/dist/debug/decoding/general.js +2 -3
- package/dist/debug/decoding/general.js.map +1 -1
- package/dist/debug/decoding/memory.d.ts.map +1 -1
- package/dist/debug/decoding/memory.js +4 -5
- package/dist/debug/decoding/memory.js.map +1 -1
- package/dist/debug/decoding/stack.js +2 -3
- package/dist/debug/decoding/stack.js.map +1 -1
- package/dist/debug/decoding/storage.d.ts.map +1 -1
- package/dist/debug/decoding/storage.js +9 -9
- package/dist/debug/decoding/storage.js.map +1 -1
- package/dist/debug/foundry_cheatcodes.d.ts +26 -25
- package/dist/debug/foundry_cheatcodes.d.ts.map +1 -1
- package/dist/debug/foundry_cheatcodes.js +114 -113
- package/dist/debug/foundry_cheatcodes.js.map +1 -1
- package/dist/debug/opcode_interposing.d.ts +2 -1
- package/dist/debug/opcode_interposing.d.ts.map +1 -1
- package/dist/debug/opcode_interposing.js +32 -30
- package/dist/debug/opcode_interposing.js.map +1 -1
- package/dist/debug/opcodes.js +6 -6
- package/dist/debug/opcodes.js.map +1 -1
- package/dist/debug/sol_debugger.d.ts +10 -165
- package/dist/debug/sol_debugger.d.ts.map +1 -1
- package/dist/debug/sol_debugger.js +73 -96
- package/dist/debug/sol_debugger.js.map +1 -1
- package/dist/debug/types.d.ts +157 -0
- package/dist/debug/types.d.ts.map +1 -1
- package/dist/debug/types.js +14 -0
- package/dist/debug/types.js.map +1 -1
- package/dist/utils/index.d.ts +2 -2
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -2
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/misc.d.ts +12 -20
- package/dist/utils/misc.d.ts.map +1 -1
- package/dist/utils/misc.js +39 -83
- package/dist/utils/misc.js.map +1 -1
- package/dist/utils/pp.d.ts.map +1 -1
- package/dist/utils/pp.js +10 -10
- package/dist/utils/pp.js.map +1 -1
- package/dist/utils/srcmap.js +2 -3
- package/dist/utils/srcmap.js.map +1 -1
- package/dist/utils/test_runner.d.ts +6 -6
- package/dist/utils/test_runner.d.ts.map +1 -1
- package/dist/utils/test_runner.js +11 -9
- package/dist/utils/test_runner.js.map +1 -1
- package/package.json +14 -12
|
@@ -1,166 +1,12 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import { Block } from "@ethereumjs/block";
|
|
3
|
-
import {
|
|
2
|
+
import { EVMStateManagerInterface } from "@ethereumjs/common";
|
|
4
3
|
import { InterpreterStep } from "@ethereumjs/evm";
|
|
5
|
-
import {
|
|
4
|
+
import { TypedTransaction } from "@ethereumjs/tx";
|
|
6
5
|
import { RunTxResult, VM } from "@ethereumjs/vm";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { DecodedBytecodeSourceMapEntry, HexString, ImmMap } from "..";
|
|
6
|
+
import { ASTNode } from "solc-typed-ast";
|
|
7
|
+
import { DecodedBytecodeSourceMapEntry } from "..";
|
|
10
8
|
import { ContractInfo, IArtifactManager } from "./artifact_manager";
|
|
11
|
-
import {
|
|
12
|
-
export declare enum FrameKind {
|
|
13
|
-
Call = "call",
|
|
14
|
-
Creation = "creation",
|
|
15
|
-
InternalCall = "internal_call"
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Base interface for Stack frames maintained by the debugger
|
|
19
|
-
*/
|
|
20
|
-
interface BaseFrame {
|
|
21
|
-
readonly kind: FrameKind;
|
|
22
|
-
/**
|
|
23
|
-
* AST node causing the call. Note that this is not always a FunctionCall. For example this could be:
|
|
24
|
-
* 1. A contract public state var VariableDeclaration
|
|
25
|
-
* 2. Any checked arithmetic operation in sol > 0.8.0 (these are implemented as internal functions)
|
|
26
|
-
* 3. Some other random non-call AST node, that is implemented as a compiler generated function
|
|
27
|
-
*/
|
|
28
|
-
readonly callee: ASTNode | undefined;
|
|
29
|
-
/**
|
|
30
|
-
* If we have a `callee` try and infer where the arguments are placed in the VM state. Some arguments may not
|
|
31
|
-
* exist in the case of msg.data generated from a fuzzer for example.
|
|
32
|
-
*/
|
|
33
|
-
readonly arguments: Array<[string, DataView | undefined]> | undefined;
|
|
34
|
-
readonly startStep: number;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Base class for a stack frame corresponding to an external call.
|
|
38
|
-
*/
|
|
39
|
-
interface BaseExternalFrame extends BaseFrame {
|
|
40
|
-
readonly sender: HexString;
|
|
41
|
-
readonly msgData: Buffer;
|
|
42
|
-
readonly address: Address;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Stack frame corresponding to an external call
|
|
46
|
-
*/
|
|
47
|
-
interface CallFrame extends BaseExternalFrame {
|
|
48
|
-
readonly kind: FrameKind.Call;
|
|
49
|
-
readonly receiver: HexString;
|
|
50
|
-
readonly code: Buffer;
|
|
51
|
-
readonly info?: ContractInfo;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Stack frame corresponding to a contract creation call
|
|
55
|
-
*/
|
|
56
|
-
interface CreationFrame extends BaseExternalFrame {
|
|
57
|
-
readonly kind: FrameKind.Creation;
|
|
58
|
-
readonly creationCode: Buffer;
|
|
59
|
-
readonly info?: ContractInfo;
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Stack frame corresponding to an internal function call
|
|
63
|
-
*/
|
|
64
|
-
interface InternalCallFrame extends BaseFrame {
|
|
65
|
-
readonly kind: FrameKind.InternalCall;
|
|
66
|
-
readonly nearestExtFrame: CallFrame | CreationFrame;
|
|
67
|
-
readonly offset: number;
|
|
68
|
-
}
|
|
69
|
-
export type ExternalFrame = CallFrame | CreationFrame;
|
|
70
|
-
export type Frame = ExternalFrame | InternalCallFrame;
|
|
71
|
-
export type DbgStack = Frame[];
|
|
72
|
-
export declare enum DataLocationKind {
|
|
73
|
-
Stack = "stack",
|
|
74
|
-
Memory = "memory",
|
|
75
|
-
Storage = "storage",
|
|
76
|
-
CallData = "calldata"
|
|
77
|
-
}
|
|
78
|
-
export type MemoryLocationKind = DataLocationKind.Memory | DataLocationKind.CallData | DataLocationKind.Storage;
|
|
79
|
-
export interface BaseDataLocation {
|
|
80
|
-
kind: DataLocationKind;
|
|
81
|
-
}
|
|
82
|
-
export interface StackLocation extends BaseDataLocation {
|
|
83
|
-
kind: DataLocationKind.Stack;
|
|
84
|
-
offsetFromTop: number;
|
|
85
|
-
}
|
|
86
|
-
export interface BaseMemoryLocation extends BaseDataLocation {
|
|
87
|
-
address: bigint;
|
|
88
|
-
}
|
|
89
|
-
export interface CalldataLocation extends BaseMemoryLocation {
|
|
90
|
-
kind: DataLocationKind.CallData;
|
|
91
|
-
}
|
|
92
|
-
export interface LinearMemoryLocation extends BaseMemoryLocation {
|
|
93
|
-
kind: DataLocationKind.Memory;
|
|
94
|
-
}
|
|
95
|
-
export interface StorageLocation extends BaseMemoryLocation {
|
|
96
|
-
kind: DataLocationKind.Storage;
|
|
97
|
-
endOffsetInWord: number;
|
|
98
|
-
}
|
|
99
|
-
export type ByteAddressableMemoryLocation = CalldataLocation | LinearMemoryLocation;
|
|
100
|
-
export type MemoryLocation = ByteAddressableMemoryLocation | StorageLocation;
|
|
101
|
-
export type DataLocation = StackLocation | MemoryLocation;
|
|
102
|
-
export interface DataView {
|
|
103
|
-
type: TypeNode;
|
|
104
|
-
abiType?: TypeNode;
|
|
105
|
-
loc: DataLocation;
|
|
106
|
-
}
|
|
107
|
-
export type Memory = Buffer;
|
|
108
|
-
export type Stack = Buffer[];
|
|
109
|
-
export type Storage = ImmMap<bigint, Buffer>;
|
|
110
|
-
export interface EventDesc {
|
|
111
|
-
payload: Buffer;
|
|
112
|
-
topics: bigint[];
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* TODO(dimo): Make memory and storage be computed only for instructions that change them, and for all other
|
|
116
|
-
* instructions alias the previous steps' memory/storage
|
|
117
|
-
*
|
|
118
|
-
* Low-level machine state at a given trace step. It directly mirrors the state reported from Web3
|
|
119
|
-
* and doesn't include any higher-level information that requires debug info.
|
|
120
|
-
*/
|
|
121
|
-
export interface StepVMState {
|
|
122
|
-
evmStack: Stack;
|
|
123
|
-
memory: Memory;
|
|
124
|
-
storage: Storage;
|
|
125
|
-
op: EVMOpInfo;
|
|
126
|
-
pc: number;
|
|
127
|
-
gasCost: bigint;
|
|
128
|
-
dynamicGasCost: bigint;
|
|
129
|
-
gas: bigint;
|
|
130
|
-
depth: number;
|
|
131
|
-
address: Address;
|
|
132
|
-
codeAddress: Address;
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* State that the debugger maintains for each trace step.
|
|
136
|
-
* It includes the basic VM state (`StepVmState`) and optionally (if we have debug info for this contract)
|
|
137
|
-
* includes the decoded source location, any AST nodes that are mapped to this instruction and any events
|
|
138
|
-
* that may be emitted on this step.
|
|
139
|
-
*/
|
|
140
|
-
export interface StepState extends StepVMState {
|
|
141
|
-
code: Buffer;
|
|
142
|
-
codeMdHash: HexString | undefined;
|
|
143
|
-
stack: DbgStack;
|
|
144
|
-
src: DecodedBytecodeSourceMapEntry | undefined;
|
|
145
|
-
astNode: ASTNode | undefined;
|
|
146
|
-
emittedEvent: EventDesc | undefined;
|
|
147
|
-
contractInfo: ContractInfo | undefined;
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Trace step struct contained in the array returned by web3.debug.traceTransaction().
|
|
151
|
-
* We translate this into `StepVmState`.
|
|
152
|
-
*/
|
|
153
|
-
export interface Web3DbgState {
|
|
154
|
-
stack: HexString[];
|
|
155
|
-
memory: HexString[];
|
|
156
|
-
storage?: any;
|
|
157
|
-
op: string;
|
|
158
|
-
pc: number;
|
|
159
|
-
gasCost: string;
|
|
160
|
-
gas: string;
|
|
161
|
-
depth: number;
|
|
162
|
-
error?: any;
|
|
163
|
-
}
|
|
9
|
+
import { DbgStack, ExternalFrame, Frame, StepState } from "./types";
|
|
164
10
|
/**
|
|
165
11
|
* Give a stack or a stack frame, find the last **external** stack frame under it (include itself).
|
|
166
12
|
*/
|
|
@@ -219,7 +65,7 @@ export declare class SolTxDebugger {
|
|
|
219
65
|
* @param trace - trace up to the current state
|
|
220
66
|
*/
|
|
221
67
|
private getCodeAndMdHash;
|
|
222
|
-
processRawTraceStep(vm: VM, stateManager:
|
|
68
|
+
processRawTraceStep(vm: VM, stateManager: EVMStateManagerInterface, step: InterpreterStep, trace: StepState[], stack: Frame[]): Promise<StepState>;
|
|
223
69
|
private static getEVM;
|
|
224
70
|
/**
|
|
225
71
|
* Releases references to the EVM stored inside VM from the
|
|
@@ -229,10 +75,10 @@ export declare class SolTxDebugger {
|
|
|
229
75
|
* used.
|
|
230
76
|
*/
|
|
231
77
|
static releaseVM(vm: VM): void;
|
|
232
|
-
static createVm(stateManager:
|
|
233
|
-
debugTx(tx:
|
|
78
|
+
static createVm(stateManager: EVMStateManagerInterface | undefined, foundryCheatcodes: boolean): Promise<VM>;
|
|
79
|
+
debugTx(tx: TypedTransaction, block: Block | undefined, stateManager: EVMStateManagerInterface): Promise<[StepState[], RunTxResult]>;
|
|
234
80
|
/**
|
|
235
|
-
* Build a `CreationFrame` from the given `sender` address, `data` `
|
|
81
|
+
* Build a `CreationFrame` from the given `sender` address, `data` `Uint8Array`(msg.data) and the current trace step number.
|
|
236
82
|
*/
|
|
237
83
|
private makeCreationFrame;
|
|
238
84
|
/**
|
|
@@ -243,7 +89,7 @@ export declare class SolTxDebugger {
|
|
|
243
89
|
*/
|
|
244
90
|
private findEntryPoint;
|
|
245
91
|
/**
|
|
246
|
-
* Build a `CallFrame` from the given `sender` address, `receiver` address, `data` `
|
|
92
|
+
* Build a `CallFrame` from the given `sender` address, `receiver` address, `data` `Uint8Array`, (msg.data) and the current trace step number.
|
|
247
93
|
*/
|
|
248
94
|
private makeCallFrame;
|
|
249
95
|
/**
|
|
@@ -264,5 +110,4 @@ export declare class SolTxDebugger {
|
|
|
264
110
|
*/
|
|
265
111
|
private decodeFunArgs;
|
|
266
112
|
}
|
|
267
|
-
export {};
|
|
268
113
|
//# sourceMappingURL=sol_debugger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sol_debugger.d.ts","sourceRoot":"","sources":["../../src/debug/sol_debugger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sol_debugger.d.ts","sourceRoot":"","sources":["../../src/debug/sol_debugger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,OAAO,EAAiB,wBAAwB,EAAY,MAAM,oBAAoB,CAAC;AACvF,OAAO,EAAO,eAAe,EAAmB,MAAM,iBAAiB,CAAC;AAGxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,EAAE,OAAO,EAA6D,MAAM,gBAAgB,CAAC;AAEpG,OAAO,EACH,6BAA6B,EAQhC,MAAM,IAAI,CAAC;AAIZ,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAgB,MAAM,oBAAoB,CAAC;AAUlF,OAAO,EAKH,QAAQ,EAGR,aAAa,EACb,KAAK,EAKL,SAAS,EAGZ,MAAM,SAAS,CAAC;AAIjB;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,KAAK,GAAG,QAAQ,GAAG,aAAa,CAItE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,KAAK,GAAG,QAAQ,GAAG,YAAY,GAAG,SAAS,CAI/E;AAiBD,MAAM,WAAW,iBAAiB;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAQD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,aAAa;IAEtB,SAAgB,eAAe,EAAE,gBAAgB,CAAC;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAU;gBAEhC,eAAe,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,iBAAiB;IAgBvE;;;;;;;;OAQG;YACW,gBAAgB;IA2K9B;;;;;;;;;;;;OAYG;YACW,gBAAgB;IA8CxB,mBAAmB,CACrB,EAAE,EAAE,EAAE,EACN,YAAY,EAAE,wBAAwB,EACtC,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,SAAS,EAAE,EAClB,KAAK,EAAE,KAAK,EAAE,GACf,OAAO,CAAC,SAAS,CAAC;mBAoFA,MAAM;IAmC3B;;;;;;OAMG;IACH,MAAM,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,IAAI;WAUjB,QAAQ,CACjB,YAAY,EAAE,wBAAwB,GAAG,SAAS,EAClD,iBAAiB,EAAE,OAAO,GAC3B,OAAO,CAAC,EAAE,CAAC;IA0BR,OAAO,CACT,EAAE,EAAE,gBAAgB,EACpB,KAAK,EAAE,KAAK,GAAG,SAAS,EACxB,YAAY,EAAE,wBAAwB,GACvC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE,WAAW,CAAC,CAAC;IA2DtC;;OAEG;YACW,iBAAiB;IA0B/B;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IActB;;OAEG;YACW,aAAa;IAqD3B;;;;;;;;;OASG;IACH,eAAe,CACX,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,aAAa,GACnB,CAAC,6BAA6B,GAAG,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC;IAiBnE;;;;OAIG;IACH,OAAO,CAAC,aAAa;CAoDxB"}
|
|
@@ -1,57 +1,48 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SolTxDebugger =
|
|
3
|
+
exports.SolTxDebugger = void 0;
|
|
4
|
+
exports.lastExternalFrame = lastExternalFrame;
|
|
5
|
+
exports.getContractInfo = getContractInfo;
|
|
4
6
|
const blockchain_1 = require("@ethereumjs/blockchain");
|
|
5
7
|
const common_1 = require("@ethereumjs/common");
|
|
6
|
-
const evm_1 = require("@ethereumjs/evm
|
|
8
|
+
const evm_1 = require("@ethereumjs/evm");
|
|
9
|
+
const rlp_1 = require("@ethereumjs/rlp");
|
|
7
10
|
const statemanager_1 = require("@ethereumjs/statemanager");
|
|
11
|
+
const util_1 = require("@ethereumjs/util");
|
|
8
12
|
const vm_1 = require("@ethereumjs/vm");
|
|
9
|
-
const
|
|
13
|
+
const utils_1 = require("ethereum-cryptography/utils");
|
|
10
14
|
const solc_typed_ast_1 = require("solc-typed-ast");
|
|
15
|
+
const stream_1 = require("stream");
|
|
11
16
|
const __1 = require("..");
|
|
12
17
|
const artifacts_1 = require("../artifacts");
|
|
18
|
+
const utils_2 = require("../utils");
|
|
13
19
|
const abi_1 = require("./abi");
|
|
14
|
-
const utils_1 = require("../utils");
|
|
15
20
|
const artifact_manager_1 = require("./artifact_manager");
|
|
16
21
|
const decoding_1 = require("./decoding");
|
|
17
22
|
const foundry_cheatcodes_1 = require("./foundry_cheatcodes");
|
|
18
|
-
const opcodes_1 = require("@ethereumjs/evm/dist/opcodes");
|
|
19
23
|
const opcode_interposing_1 = require("./opcode_interposing");
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
var FrameKind;
|
|
23
|
-
(function (FrameKind) {
|
|
24
|
-
FrameKind["Call"] = "call";
|
|
25
|
-
FrameKind["Creation"] = "creation";
|
|
26
|
-
FrameKind["InternalCall"] = "internal_call";
|
|
27
|
-
})(FrameKind || (exports.FrameKind = FrameKind = {}));
|
|
28
|
-
var DataLocationKind;
|
|
29
|
-
(function (DataLocationKind) {
|
|
30
|
-
DataLocationKind["Stack"] = "stack";
|
|
31
|
-
DataLocationKind["Memory"] = "memory";
|
|
32
|
-
DataLocationKind["Storage"] = "storage";
|
|
33
|
-
DataLocationKind["CallData"] = "calldata";
|
|
34
|
-
})(DataLocationKind || (exports.DataLocationKind = DataLocationKind = {}));
|
|
24
|
+
const opcodes_1 = require("./opcodes");
|
|
25
|
+
const types_1 = require("./types");
|
|
35
26
|
// Helper functions
|
|
36
27
|
/**
|
|
37
28
|
* Give a stack or a stack frame, find the last **external** stack frame under it (include itself).
|
|
38
29
|
*/
|
|
39
30
|
function lastExternalFrame(arg) {
|
|
40
31
|
const frame = arg instanceof Array ? arg[arg.length - 1] : arg;
|
|
41
|
-
return frame.kind === FrameKind.InternalCall ? frame.nearestExtFrame : frame;
|
|
32
|
+
return frame.kind === types_1.FrameKind.InternalCall ? frame.nearestExtFrame : frame;
|
|
42
33
|
}
|
|
43
|
-
exports.lastExternalFrame = lastExternalFrame;
|
|
44
34
|
function getContractInfo(arg) {
|
|
45
35
|
const frame = lastExternalFrame(arg);
|
|
46
36
|
return frame.info;
|
|
47
37
|
}
|
|
48
|
-
exports.getContractInfo = getContractInfo;
|
|
49
38
|
async function getStorage(manager, addr) {
|
|
50
39
|
const rawStorage = await manager.dumpStorage(addr);
|
|
51
40
|
const storageEntries = [];
|
|
52
41
|
for (const [keyStr, valStr] of Object.entries(rawStorage)) {
|
|
53
|
-
const
|
|
54
|
-
|
|
42
|
+
const decoded = rlp_1.RLP.decode((0, utils_1.hexToBytes)(valStr));
|
|
43
|
+
(0, solc_typed_ast_1.assert)(decoded instanceof Uint8Array, "");
|
|
44
|
+
const valBuf = (0, util_1.setLengthLeft)(decoded, 32);
|
|
45
|
+
storageEntries.push([BigInt(keyStr), valBuf]);
|
|
55
46
|
}
|
|
56
47
|
return __1.ImmMap.fromEntries(storageEntries);
|
|
57
48
|
}
|
|
@@ -114,23 +105,23 @@ class SolTxDebugger {
|
|
|
114
105
|
if (lastStep.depth !== state.depth) {
|
|
115
106
|
const lastStackTop = lastStep.evmStack.length - 1;
|
|
116
107
|
if (state.depth > lastStep.depth) {
|
|
117
|
-
(0, solc_typed_ast_1.assert)((0,
|
|
118
|
-
if ((0,
|
|
108
|
+
(0, solc_typed_ast_1.assert)((0, opcodes_1.increasesDepth)(lastOp), `Unexpected depth increase on op ${lastOp.mnemonic}`);
|
|
109
|
+
if ((0, opcodes_1.createsContract)(lastOp)) {
|
|
119
110
|
// Contract creation call
|
|
120
|
-
const off = (0,
|
|
121
|
-
const size = (0,
|
|
111
|
+
const off = (0, utils_2.bigEndianBufToNumber)(lastStep.evmStack[lastStackTop - 1]);
|
|
112
|
+
const size = (0, utils_2.bigEndianBufToNumber)(lastStep.evmStack[lastStackTop - 2]);
|
|
122
113
|
const creationBytecode = lastStep.memory.slice(off, off + size);
|
|
123
114
|
const curFrame = await this.makeCreationFrame(lastExtFrame.address.toString(), creationBytecode, trace.length);
|
|
124
115
|
stack.push(curFrame);
|
|
125
116
|
}
|
|
126
117
|
else {
|
|
127
118
|
// External call
|
|
128
|
-
const argStackOff = lastOp.opcode ===
|
|
119
|
+
const argStackOff = lastOp.opcode === opcodes_1.OPCODES.CALL || lastOp.opcode === opcodes_1.OPCODES.CALLCODE
|
|
129
120
|
? 3
|
|
130
121
|
: 2;
|
|
131
122
|
const argSizeStackOff = argStackOff + 1;
|
|
132
|
-
const argOff = (0,
|
|
133
|
-
const argSize = (0,
|
|
123
|
+
const argOff = (0, utils_2.bigEndianBufToNumber)(lastStep.evmStack[lastStackTop - argStackOff]);
|
|
124
|
+
const argSize = (0, utils_2.bigEndianBufToNumber)(lastStep.evmStack[lastStackTop - argSizeStackOff]);
|
|
134
125
|
const receiver = (0, __1.wordToAddress)(lastStep.evmStack[lastStackTop - 1]);
|
|
135
126
|
const msgData = lastStep.memory.slice(argOff, argOff + argSize);
|
|
136
127
|
const newFrame = await this.makeCallFrame(lastExtFrame.address.toString(), receiver, msgData, code, codeHash, trace.length);
|
|
@@ -144,7 +135,7 @@ class SolTxDebugger {
|
|
|
144
135
|
// depth reported by web3. We need the loop since we don't count the internal frames as decreasing depth
|
|
145
136
|
while (nFramesPopped > 0 && stack.length > 0) {
|
|
146
137
|
const topFrame = stack[stack.length - 1];
|
|
147
|
-
if (topFrame.kind === FrameKind.Creation || topFrame.kind === FrameKind.Call) {
|
|
138
|
+
if (topFrame.kind === types_1.FrameKind.Creation || topFrame.kind === types_1.FrameKind.Call) {
|
|
148
139
|
nFramesPopped--;
|
|
149
140
|
}
|
|
150
141
|
stack.pop();
|
|
@@ -186,7 +177,7 @@ class SolTxDebugger {
|
|
|
186
177
|
args = this.decodeFunArgs(ast, state.evmStack, curExtFrame.info);
|
|
187
178
|
}
|
|
188
179
|
const newFrame = {
|
|
189
|
-
kind: FrameKind.InternalCall,
|
|
180
|
+
kind: types_1.FrameKind.InternalCall,
|
|
190
181
|
nearestExtFrame: lastExtFrame,
|
|
191
182
|
callee: ast,
|
|
192
183
|
offset: state.pc,
|
|
@@ -200,11 +191,11 @@ class SolTxDebugger {
|
|
|
200
191
|
if (state.op.mnemonic === "JUMP" && src.jump === "o") {
|
|
201
192
|
const topFrame = stack[stack.length - 1];
|
|
202
193
|
if (this.strict) {
|
|
203
|
-
(0, solc_typed_ast_1.assert)(topFrame.kind === FrameKind.InternalCall, `Mismatched internal return from frame `, topFrame.kind);
|
|
194
|
+
(0, solc_typed_ast_1.assert)(topFrame.kind === types_1.FrameKind.InternalCall, `Mismatched internal return from frame `, topFrame.kind);
|
|
204
195
|
stack.pop();
|
|
205
196
|
}
|
|
206
197
|
else {
|
|
207
|
-
if (topFrame.kind === FrameKind.InternalCall) {
|
|
198
|
+
if (topFrame.kind === types_1.FrameKind.InternalCall) {
|
|
208
199
|
stack.pop();
|
|
209
200
|
}
|
|
210
201
|
// @todo log an error somewhere
|
|
@@ -228,36 +219,43 @@ class SolTxDebugger {
|
|
|
228
219
|
const lastStep = trace.length > 0 ? trace[trace.length - 1] : undefined;
|
|
229
220
|
let code;
|
|
230
221
|
let codeMdHash;
|
|
231
|
-
|
|
222
|
+
const getCodeAddress = (s) => s.codeAddress !== undefined ? s.codeAddress : s.address;
|
|
223
|
+
// Case 1: First step in the trace
|
|
224
|
+
if (lastStep === undefined) {
|
|
225
|
+
const code = await vm.stateManager.getContractCode(getCodeAddress(step));
|
|
226
|
+
const codeMdHash = (0, artifacts_1.getCodeHash)(code);
|
|
227
|
+
return [code, codeMdHash];
|
|
228
|
+
}
|
|
229
|
+
// Case 2: Just entering a constructor from another contract
|
|
230
|
+
if ((0, opcodes_1.createsContract)(lastStep.op)) {
|
|
232
231
|
const lastStackTop = lastStep.evmStack.length - 1;
|
|
233
|
-
const off = (0,
|
|
234
|
-
const size = (0,
|
|
235
|
-
code = lastStep.memory.slice(off, off + size);
|
|
236
|
-
codeMdHash = (0, artifacts_1.getCreationCodeHash)(code);
|
|
232
|
+
const off = (0, utils_2.bigEndianBufToNumber)(lastStep.evmStack[lastStackTop - 1]);
|
|
233
|
+
const size = (0, utils_2.bigEndianBufToNumber)(lastStep.evmStack[lastStackTop - 2]);
|
|
234
|
+
const code = lastStep.memory.slice(off, off + size);
|
|
235
|
+
const codeMdHash = (0, artifacts_1.getCreationCodeHash)(code);
|
|
236
|
+
return [code, codeMdHash];
|
|
237
237
|
}
|
|
238
|
-
|
|
239
|
-
|
|
238
|
+
// Case 3: The code changed - either we are in a different contract or a delegate call context
|
|
239
|
+
if (!getCodeAddress(lastStep).equals(getCodeAddress(step))) {
|
|
240
|
+
// Case 3: We are changing the code address
|
|
241
|
+
code = await vm.stateManager.getContractCode(getCodeAddress(step));
|
|
240
242
|
codeMdHash = (0, artifacts_1.getCodeHash)(code);
|
|
243
|
+
return [code, codeMdHash];
|
|
241
244
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
245
|
+
// Case 4: We are still in the same contract
|
|
246
|
+
code = lastStep.code;
|
|
247
|
+
codeMdHash = lastStep.codeMdHash;
|
|
246
248
|
return [code, codeMdHash];
|
|
247
249
|
}
|
|
248
250
|
async processRawTraceStep(vm, stateManager, step, trace, stack) {
|
|
249
|
-
const evmStack = step.stack.map((word) => (0,
|
|
251
|
+
const evmStack = step.stack.map((word) => (0, utils_2.bigIntToBuf)(word, 32, "big"));
|
|
250
252
|
const lastStep = trace.length > 0 ? trace[trace.length - 1] : undefined;
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
else {
|
|
256
|
-
memory = lastStep.memory;
|
|
257
|
-
}
|
|
258
|
-
const op = (0, opcodes_2.getOpInfo)(step.opcode.name);
|
|
253
|
+
const memory = lastStep === undefined || (0, opcodes_1.changesMemory)(lastStep.op)
|
|
254
|
+
? new Uint8Array(step.memory)
|
|
255
|
+
: lastStep.memory;
|
|
256
|
+
const op = (0, opcodes_1.getOpInfo)(step.opcode.name);
|
|
259
257
|
let storage;
|
|
260
|
-
if (lastStep === undefined || lastStep.op.opcode ===
|
|
258
|
+
if (lastStep === undefined || lastStep.op.opcode === opcodes_1.OPCODES.SSTORE) {
|
|
261
259
|
storage = await getStorage(stateManager, step.address);
|
|
262
260
|
}
|
|
263
261
|
else {
|
|
@@ -293,8 +291,8 @@ class SolTxDebugger {
|
|
|
293
291
|
let emittedEvent = undefined;
|
|
294
292
|
// Finally check if an event is being emitted for this step
|
|
295
293
|
if (step.opcode.name.startsWith("LOG")) {
|
|
296
|
-
const off = (0,
|
|
297
|
-
const size = (0,
|
|
294
|
+
const off = (0, utils_2.bigEndianBufToNumber)(evmStack[evmStack.length - 1]);
|
|
295
|
+
const size = (0, utils_2.bigEndianBufToNumber)(evmStack[evmStack.length - 2]);
|
|
298
296
|
const nTopics = step.opcode.name[3] - "0";
|
|
299
297
|
const payload = memory.slice(off, off + size);
|
|
300
298
|
emittedEvent = {
|
|
@@ -321,7 +319,7 @@ class SolTxDebugger {
|
|
|
321
319
|
if (!foundryCheatcodes) {
|
|
322
320
|
return tmpEvm;
|
|
323
321
|
}
|
|
324
|
-
const opcodes = (0,
|
|
322
|
+
const opcodes = (0, evm_1.getOpcodesForHF)(tmpEvm.common);
|
|
325
323
|
const [precompile, foundryCtx] = (0, foundry_cheatcodes_1.makeFoundryCheatcodePrecompile)();
|
|
326
324
|
const optsCopy = {
|
|
327
325
|
...opts,
|
|
@@ -365,8 +363,7 @@ class SolTxDebugger {
|
|
|
365
363
|
if (!stateManager) {
|
|
366
364
|
stateManager = new statemanager_1.DefaultStateManager();
|
|
367
365
|
}
|
|
368
|
-
const
|
|
369
|
-
const evm = await SolTxDebugger.getEVM({ common, eei, allowUnlimitedContractSize: true }, foundryCheatcodes);
|
|
366
|
+
const evm = await SolTxDebugger.getEVM({ common, blockchain, stateManager, allowUnlimitedContractSize: true }, foundryCheatcodes);
|
|
370
367
|
const vm = await vm_1.VM.create({
|
|
371
368
|
common,
|
|
372
369
|
blockchain,
|
|
@@ -378,7 +375,7 @@ class SolTxDebugger {
|
|
|
378
375
|
return vm;
|
|
379
376
|
}
|
|
380
377
|
async debugTx(tx, block, stateManager) {
|
|
381
|
-
const vm = await SolTxDebugger.createVm(stateManager, this.foundryCheatcodes);
|
|
378
|
+
const vm = await SolTxDebugger.createVm(stateManager.shallowCopy(true), this.foundryCheatcodes);
|
|
382
379
|
const sender = tx.getSenderAddress().toString();
|
|
383
380
|
const receiver = tx.to === undefined ? __1.ZERO_ADDRESS_STRING : tx.to.toString();
|
|
384
381
|
const isCreation = receiver === __1.ZERO_ADDRESS_STRING;
|
|
@@ -388,7 +385,7 @@ class SolTxDebugger {
|
|
|
388
385
|
curFrame = await this.makeCreationFrame(sender, tx.data, 0);
|
|
389
386
|
}
|
|
390
387
|
else {
|
|
391
|
-
(0, solc_typed_ast_1.assert)(tx.to !== undefined, 'Expected "to" of tx {0} to be defined, got undefined instead', tx.hash()
|
|
388
|
+
(0, solc_typed_ast_1.assert)(tx.to !== undefined, 'Expected "to" of tx {0} to be defined, got undefined instead', (0, utils_1.bytesToHex)(tx.hash()));
|
|
392
389
|
const code = await vm.stateManager.getContractCode(tx.to);
|
|
393
390
|
/// @todo remove - arbitrary restriction, only good for debugging
|
|
394
391
|
(0, solc_typed_ast_1.assert)(code.length > 0, "Missing code for address {0}", tx.to.toString());
|
|
@@ -414,7 +411,7 @@ class SolTxDebugger {
|
|
|
414
411
|
return [trace, txRes];
|
|
415
412
|
}
|
|
416
413
|
/**
|
|
417
|
-
* Build a `CreationFrame` from the given `sender` address, `data` `
|
|
414
|
+
* Build a `CreationFrame` from the given `sender` address, `data` `Uint8Array`(msg.data) and the current trace step number.
|
|
418
415
|
*/
|
|
419
416
|
async makeCreationFrame(sender, data, step) {
|
|
420
417
|
const contractInfo = await this.artifactManager.getContractFromCreationBytecode(data);
|
|
@@ -424,7 +421,7 @@ class SolTxDebugger {
|
|
|
424
421
|
// TODO: Try and find the arguments inside the creation code and decode them
|
|
425
422
|
}
|
|
426
423
|
return {
|
|
427
|
-
kind: FrameKind.Creation,
|
|
424
|
+
kind: types_1.FrameKind.Creation,
|
|
428
425
|
sender,
|
|
429
426
|
msgData: data,
|
|
430
427
|
creationCode: data,
|
|
@@ -447,38 +444,16 @@ class SolTxDebugger {
|
|
|
447
444
|
}
|
|
448
445
|
const contract = info.ast;
|
|
449
446
|
const infer = this.artifactManager.infer(info.artifact.compilerVersion);
|
|
450
|
-
|
|
451
|
-
// Need to be defensive here, as in some cases with partial AST information the base may be missing
|
|
452
|
-
if (base === undefined) {
|
|
453
|
-
continue;
|
|
454
|
-
}
|
|
455
|
-
const matchingFuns = base.vFunctions.filter((fun) => (0, __1.getFunctionSelector)(fun, infer) === selector);
|
|
456
|
-
if (matchingFuns.length === 1) {
|
|
457
|
-
return matchingFuns[0];
|
|
458
|
-
}
|
|
459
|
-
const matchingGetters = base.vStateVariables.filter((vDef) => {
|
|
460
|
-
try {
|
|
461
|
-
return (vDef.visibility === solc_typed_ast_1.StateVariableVisibility.Public &&
|
|
462
|
-
infer.signatureHash(vDef));
|
|
463
|
-
}
|
|
464
|
-
catch (e) {
|
|
465
|
-
return false;
|
|
466
|
-
}
|
|
467
|
-
});
|
|
468
|
-
if (matchingGetters.length === 1) {
|
|
469
|
-
return matchingGetters[0];
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
return undefined;
|
|
447
|
+
return (0, abi_1.findMethodBySelector)(selector, contract, infer);
|
|
473
448
|
}
|
|
474
449
|
/**
|
|
475
|
-
* Build a `CallFrame` from the given `sender` address, `receiver` address, `data` `
|
|
450
|
+
* Build a `CallFrame` from the given `sender` address, `receiver` address, `data` `Uint8Array`, (msg.data) and the current trace step number.
|
|
476
451
|
*/
|
|
477
452
|
async makeCallFrame(sender, receiver, data, receiverCode, codeHash, step) {
|
|
478
453
|
const contractInfo = codeHash === undefined
|
|
479
454
|
? codeHash
|
|
480
455
|
: this.artifactManager.getContractFromMDHash(codeHash);
|
|
481
|
-
const selector = data.slice(0, 4)
|
|
456
|
+
const selector = (0, utils_1.bytesToHex)(data.slice(0, 4));
|
|
482
457
|
let callee;
|
|
483
458
|
let args;
|
|
484
459
|
if (contractInfo && contractInfo.ast) {
|
|
@@ -487,7 +462,7 @@ class SolTxDebugger {
|
|
|
487
462
|
callee = this.findEntryPoint(contractInfo, selector);
|
|
488
463
|
if (callee !== undefined) {
|
|
489
464
|
try {
|
|
490
|
-
args = (0, abi_1.buildMsgDataViews)(callee, data, DataLocationKind.CallData, infer, abiVersion);
|
|
465
|
+
args = (0, abi_1.buildMsgDataViews)(callee, data, types_1.DataLocationKind.CallData, infer, abiVersion);
|
|
491
466
|
}
|
|
492
467
|
catch (e) {
|
|
493
468
|
args = undefined;
|
|
@@ -495,7 +470,7 @@ class SolTxDebugger {
|
|
|
495
470
|
}
|
|
496
471
|
}
|
|
497
472
|
return {
|
|
498
|
-
kind: FrameKind.Call,
|
|
473
|
+
kind: types_1.FrameKind.Call,
|
|
499
474
|
sender,
|
|
500
475
|
msgData: data,
|
|
501
476
|
receiver: receiver.toString(),
|
|
@@ -521,7 +496,7 @@ class SolTxDebugger {
|
|
|
521
496
|
if (!ctx.info) {
|
|
522
497
|
return [undefined, undefined];
|
|
523
498
|
}
|
|
524
|
-
const bytecodeInfo = ctx.kind === FrameKind.Creation ? ctx.info.bytecode : ctx.info.deployedBytecode;
|
|
499
|
+
const bytecodeInfo = ctx.kind === types_1.FrameKind.Creation ? ctx.info.bytecode : ctx.info.deployedBytecode;
|
|
525
500
|
const src = (0, artifact_manager_1.getOffsetSrc)(instrOffset, bytecodeInfo);
|
|
526
501
|
const astNode = ctx.info.artifact.srcMap.get(`${src.start}:${src.length}:${src.sourceIndex}`);
|
|
527
502
|
return [src, astNode];
|
|
@@ -542,7 +517,9 @@ class SolTxDebugger {
|
|
|
542
517
|
argDef.name,
|
|
543
518
|
infer.variableDeclarationToTypeNode(argDef)
|
|
544
519
|
])
|
|
545
|
-
: infer
|
|
520
|
+
: infer
|
|
521
|
+
.getterArgsAndReturn(callee)[0]
|
|
522
|
+
.map((typ, i) => [`ARG_${i}`, typ]);
|
|
546
523
|
}
|
|
547
524
|
catch (e) {
|
|
548
525
|
// `variableDeclarationToTypeNode` may fail when referencing structs/contracts that are defined
|
|
@@ -563,7 +540,7 @@ class SolTxDebugger {
|
|
|
563
540
|
{
|
|
564
541
|
type: typ,
|
|
565
542
|
loc: {
|
|
566
|
-
kind: DataLocationKind.Stack,
|
|
543
|
+
kind: types_1.DataLocationKind.Stack,
|
|
567
544
|
offsetFromTop
|
|
568
545
|
}
|
|
569
546
|
}
|