Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change edr_napi::provider::Response::solidity_trace to return a stack trace #734

Draft
wants to merge 24 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
83b57b0
Duplicate stack trace logic in Rust
agostbiro Dec 3, 2024
3f87c6f
wip
fvictorio Dec 4, 2024
fad1358
Set throwOnTransactionFailures true and get tx hash from error
agostbiro Dec 4, 2024
70ee8de
refactor: pass tracing config to provider (#738)
agostbiro Dec 5, 2024
36059bb
Remove solidity_trace getter from Response
agostbiro Dec 5, 2024
781b57e
Remove duplicated NAPI logic
agostbiro Dec 5, 2024
748b678
remove getContractAndFunctionNameCallback
agostbiro Dec 6, 2024
5277a66
Add link_hex_string_bytecode back to edr_napi
fvictorio Dec 6, 2024
8e59550
Adapt hardhat patch to latest changes
fvictorio Dec 6, 2024
433ad4d
Remove unused stuff in hardhat-tests
fvictorio Dec 6, 2024
4cef55a
Refactor for type safety
agostbiro Dec 10, 2024
8de6f2e
Make build model Send + Sync
agostbiro Dec 19, 2024
fad2851
Add hardhat_addCompilationResult
agostbiro Dec 19, 2024
19eed93
Remove hardhat_getStackTraceFailuresCount logic
fvictorio Dec 20, 2024
5f34c04
Fix missing argument in test
fvictorio Dec 20, 2024
0e9e26d
Fix lint:fix script in hardhat-tests
fvictorio Dec 20, 2024
27f6e3c
Remove useless code
fvictorio Dec 20, 2024
71d4722
Ignore dot-notation rule for private field
fvictorio Dec 20, 2024
c3a8cd3
Fix compilation issues in edr_napi ts tests
fvictorio Dec 20, 2024
218290f
Move lock inside contract decoder
agostbiro Dec 20, 2024
a16338c
Fix naming
agostbiro Dec 20, 2024
86a6178
Add test for hardhat_addCompilationResult
fvictorio Dec 23, 2024
5308fcc
Cleanup stack traces tests code
fvictorio Dec 23, 2024
b8f0703
Create dirty-humans-exercise.md
fvictorio Dec 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/dirty-humans-exercise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nomicfoundation/edr": minor
---

Add a `stackTrace` getter to the provider's response and remove the old, lower-level `solidityTrace` getter.
40 changes: 24 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions crates/edr_evm/src/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ pub struct Trace {
#[derive(Clone, Debug)]
pub struct Step {
/// The program counter
pub pc: u64,
pub pc: u32,
/// The call depth
pub depth: u64,
/// The executed op code
Expand Down Expand Up @@ -491,7 +491,10 @@ impl TraceCollector {
None
};
self.current_trace_mut().add_step(Step {
pc: interp.program_counter() as u64,
pc: interp
.program_counter()
.try_into()
.expect("program counter fits into u32"),
depth: data.journaled_state.depth(),
opcode: interp.current_opcode(),
stack,
Expand Down
106 changes: 16 additions & 90 deletions crates/edr_napi/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,6 @@ export interface LoggerConfig {
/** Whether to enable the logger. */
enable: boolean
decodeConsoleLogInputsCallback: (inputs: Buffer[]) => string[]
/** Used to resolve the contract and function name when logging. */
getContractAndFunctionNameCallback: (code: Buffer, calldata?: Buffer) => ContractAndFunctionName
printLineCallback: (message: string, replace: boolean) => void
}
/** Configuration for a chain */
Expand Down Expand Up @@ -346,18 +344,7 @@ export interface SubscriptionEvent {
filterId: bigint
result: any
}
export declare function createModelsAndDecodeBytecodes(solcVersion: string, compilerInput: any, compilerOutput: any): Array<BytecodeWrapper>
export declare function linkHexStringBytecode(code: string, address: string, position: number): string
export const enum ContractFunctionType {
CONSTRUCTOR = 0,
FUNCTION = 1,
FALLBACK = 2,
RECEIVE = 3,
GETTER = 4,
MODIFIER = 5,
FREE_FUNCTION = 6
}
export declare function printMessageTrace(trace: PrecompileMessageTrace | CallMessageTrace | CreateMessageTrace, depth?: number | undefined | null): void
export declare function printStackTrace(trace: SolidityStackTrace): void
/** Represents the exit code of the EVM. */
export const enum ExitCode {
Expand All @@ -380,51 +367,14 @@ export const enum ExitCode {
/** Unknown halt reason. */
UNKNOWN_HALT_REASON = 8
}
export interface EvmStep {
pc: number
}
export interface PrecompileMessageTrace {
value: bigint
returnData: Uint8Array
exit: Exit
gasUsed: bigint
depth: number
precompile: number
calldata: Uint8Array
}
export interface CreateMessageTrace {
value: bigint
returnData: Uint8Array
exit: Exit
gasUsed: bigint
depth: number
code: Uint8Array
steps: Array<EvmStep | PrecompileMessageTrace | CallMessageTrace | CreateMessageTrace>
/**
* Reference to the resolved `Bytecode` EDR data.
* Only used on the JS side by the `VmTraceDecoder` class.
*/
bytecode?: BytecodeWrapper
numberOfSubtraces: number
deployedContract?: Uint8Array | undefined
}
export interface CallMessageTrace {
value: bigint
returnData: Uint8Array
exit: Exit
gasUsed: bigint
depth: number
code: Uint8Array
steps: Array<EvmStep | PrecompileMessageTrace | CallMessageTrace | CreateMessageTrace>
/**
* Reference to the resolved `Bytecode` EDR data.
* Only used on the JS side by the `VmTraceDecoder` class.
*/
bytecode?: BytecodeWrapper
numberOfSubtraces: number
calldata: Uint8Array
address: Uint8Array
codeAddress: Uint8Array
export const enum ContractFunctionType {
CONSTRUCTOR = 0,
FUNCTION = 1,
FALLBACK = 2,
RECEIVE = 3,
GETTER = 4,
MODIFIER = 5,
FREE_FUNCTION = 6
}
export const enum StackTraceEntryType {
CALLSTACK_ENTRY = 0,
Expand Down Expand Up @@ -580,11 +530,6 @@ export interface ContractCallRunOutOfGasError {
type: StackTraceEntryType.CONTRACT_CALL_RUN_OUT_OF_GAS_ERROR
sourceReference?: SourceReference
}
export interface ContractAndFunctionName {
contractName: string
functionName: string | undefined
}
export declare function initializeVmTraceDecoder(vmTraceDecoder: VmTraceDecoder, tracingConfig: any): void
export interface TracingMessage {
/** Sender address */
readonly caller: Buffer
Expand Down Expand Up @@ -645,7 +590,7 @@ export declare class EdrContext {
/** A JSON-RPC provider for Ethereum. */
export declare class Provider {
/**Constructs a new provider with the provided configuration. */
static withConfig(context: EdrContext, config: ProviderConfig, loggerConfig: LoggerConfig, subscriberCallback: (event: SubscriptionEvent) => void): Promise<Provider>
static withConfig(context: EdrContext, config: ProviderConfig, loggerConfig: LoggerConfig, tracingConfig: any, subscriberCallback: (event: SubscriptionEvent) => void): Promise<Provider>
/**Handles a JSON-RPC request and returns a JSON-RPC response. */
handleRequest(jsonRequest: string): Promise<Response>
setCallOverrideCallback(callOverrideCallback: (contract_address: Buffer, data: Buffer) => Promise<CallOverrideResult | undefined>): void
Expand All @@ -660,19 +605,20 @@ export declare class Provider {
export declare class Response {
/** Returns the response data as a JSON string or a JSON object. */
get data(): string | any
get solidityTrace(): RawTrace | null
get traces(): Array<RawTrace>
/**Compute the error stack trace. Return undefined if there was no error, returns the stack trace if it can be computed or returns the error message if available as a fallback. */
stackTrace(): SolidityStackTrace | string | null
}
/**
* Opaque handle to the `Bytecode` struct.
* Only used on the JS side by the `VmTraceDecoder` class.
*/
export declare class BytecodeWrapper { }
export declare class Exit {
get kind(): ExitCode
isError(): boolean
getReason(): string
}
/**
* Opaque handle to the `Bytecode` struct.
* Only used on the JS side by the `VmTraceDecoder` class.
*/
export declare class BytecodeWrapper { }
export declare class ReturnData {
readonly value: Uint8Array
constructor(value: Uint8Array)
Expand All @@ -682,26 +628,6 @@ export declare class ReturnData {
decodeError(): string
decodePanic(): bigint
}
export declare class SolidityTracer {

constructor()
getStackTrace(trace: PrecompileMessageTrace | CallMessageTrace | CreateMessageTrace): SolidityStackTrace
}
export declare class VmTraceDecoder {
constructor()
addBytecode(bytecode: BytecodeWrapper): void
tryToDecodeMessageTrace(messageTrace: PrecompileMessageTrace | CallMessageTrace | CreateMessageTrace): PrecompileMessageTrace | CallMessageTrace | CreateMessageTrace
getContractAndFunctionNamesForCall(code: Uint8Array, calldata: Uint8Array | undefined): ContractAndFunctionName
}
export type VMTracer = VmTracer
/** N-API bindings for the Rust port of `VMTracer` from Hardhat. */
export declare class VmTracer {
constructor()
/** Observes a trace, collecting information about the execution of the EVM. */
observe(trace: RawTrace): void
getLastTopLevelMessageTrace(): PrecompileMessageTrace | CallMessageTrace | CreateMessageTrace | undefined
getLastError(): Error | undefined
}
export declare class RawTrace {
trace(): Array<TracingMessage | TracingStep | TracingMessageResult>
}
12 changes: 3 additions & 9 deletions crates/edr_napi/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ if (!nativeBinding) {
throw new Error(`Failed to load native binding`)
}

const { SpecId, EdrContext, MineOrdering, Provider, Response, SuccessReason, ExceptionalHalt, createModelsAndDecodeBytecodes, linkHexStringBytecode, BytecodeWrapper, ContractFunctionType, printMessageTrace, printStackTrace, Exit, ExitCode, ReturnData, StackTraceEntryType, stackTraceEntryTypeToString, FALLBACK_FUNCTION_NAME, RECEIVE_FUNCTION_NAME, CONSTRUCTOR_FUNCTION_NAME, UNRECOGNIZED_FUNCTION_NAME, UNKNOWN_FUNCTION_NAME, PRECOMPILE_FUNCTION_NAME, UNRECOGNIZED_CONTRACT_NAME, SolidityTracer, VmTraceDecoder, initializeVmTraceDecoder, VmTracer, RawTrace } = nativeBinding
const { SpecId, EdrContext, MineOrdering, Provider, Response, SuccessReason, ExceptionalHalt, linkHexStringBytecode, printStackTrace, Exit, ExitCode, BytecodeWrapper, ContractFunctionType, ReturnData, StackTraceEntryType, stackTraceEntryTypeToString, FALLBACK_FUNCTION_NAME, RECEIVE_FUNCTION_NAME, CONSTRUCTOR_FUNCTION_NAME, UNRECOGNIZED_FUNCTION_NAME, UNKNOWN_FUNCTION_NAME, PRECOMPILE_FUNCTION_NAME, UNRECOGNIZED_CONTRACT_NAME, RawTrace } = nativeBinding

module.exports.SpecId = SpecId
module.exports.EdrContext = EdrContext
Expand All @@ -319,14 +319,12 @@ module.exports.Provider = Provider
module.exports.Response = Response
module.exports.SuccessReason = SuccessReason
module.exports.ExceptionalHalt = ExceptionalHalt
module.exports.createModelsAndDecodeBytecodes = createModelsAndDecodeBytecodes
module.exports.linkHexStringBytecode = linkHexStringBytecode
module.exports.BytecodeWrapper = BytecodeWrapper
module.exports.ContractFunctionType = ContractFunctionType
module.exports.printMessageTrace = printMessageTrace
module.exports.printStackTrace = printStackTrace
module.exports.Exit = Exit
module.exports.ExitCode = ExitCode
module.exports.BytecodeWrapper = BytecodeWrapper
module.exports.ContractFunctionType = ContractFunctionType
module.exports.ReturnData = ReturnData
module.exports.StackTraceEntryType = StackTraceEntryType
module.exports.stackTraceEntryTypeToString = stackTraceEntryTypeToString
Expand All @@ -337,8 +335,4 @@ module.exports.UNRECOGNIZED_FUNCTION_NAME = UNRECOGNIZED_FUNCTION_NAME
module.exports.UNKNOWN_FUNCTION_NAME = UNKNOWN_FUNCTION_NAME
module.exports.PRECOMPILE_FUNCTION_NAME = PRECOMPILE_FUNCTION_NAME
module.exports.UNRECOGNIZED_CONTRACT_NAME = UNRECOGNIZED_CONTRACT_NAME
module.exports.SolidityTracer = SolidityTracer
module.exports.VmTraceDecoder = VmTraceDecoder
module.exports.initializeVmTraceDecoder = initializeVmTraceDecoder
module.exports.VmTracer = VmTracer
module.exports.RawTrace = RawTrace
Loading
Loading