Skip to content

Commit a68363c

Browse files
committed
Merge remote-tracking branch 'origin/master' into valuegeneration-tracer
2 parents 30f9419 + 1ec85c7 commit a68363c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1549
-1038
lines changed

.github/workflows/ci.yml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
5252
- uses: actions/setup-go@v5
5353
with:
54-
go-version: "^1.18.1"
54+
go-version: "^1.22"
5555
# disable caching during release (tag) builds
5656
cache: ${{ !startsWith(github.ref, 'refs/tags/') }}
5757

@@ -129,7 +129,7 @@ jobs:
129129

130130
- uses: actions/setup-go@v5
131131
with:
132-
go-version: "^1.18.1"
132+
go-version: "^1.22"
133133

134134
- name: Actionlint
135135
run: |
@@ -156,6 +156,13 @@ jobs:
156156
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
157157
golangci-lint run --timeout 5m0s
158158
159+
- name: Gencodec
160+
run: |
161+
go get github.com/fjl/gencodec
162+
pushd fuzzing/config
163+
go run github.com/fjl/gencodec -type FuzzingConfig -field-override fuzzingConfigMarshaling -out gen_fuzzing_config.go
164+
git diff --exit-code -- .
165+
popd
159166
test:
160167
strategy:
161168
matrix:
@@ -197,7 +204,7 @@ jobs:
197204
198205
- uses: actions/setup-go@v5
199206
with:
200-
go-version: "^1.18.1"
207+
go-version: "^1.22"
201208

202209
- uses: actions/setup-node@v4
203210
with:

CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
* @Xenomega @anishnaik
1+
* @Xenomega @anishnaik @0xalpharush

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ To install
5959
To run
6060

6161
- `prettier '**.json' '**/*.md' '**/*.yml' '!(pkg)'`
62-
- `markdown-link-check --config .github/workflows/resources/markdown_link_check.json ./*.md`
62+
- `find . -name '*.md' -print0 | xargs -0 -n1 markdown-link-check --config .github/workflows/resources/markdown_link_check.json`
6363

6464
To format (overwrite files)
6565

chain/cheat_code_tracer.go

Lines changed: 78 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package chain
22

33
import (
4+
"math/big"
5+
46
"github.com/crytic/medusa/chain/types"
57
"github.com/ethereum/go-ethereum/common"
8+
"github.com/ethereum/go-ethereum/core/tracing"
9+
coretypes "github.com/ethereum/go-ethereum/core/types"
610
"github.com/ethereum/go-ethereum/core/vm"
7-
"math/big"
11+
"github.com/ethereum/go-ethereum/eth/tracers"
812
)
913

1014
// cheatCodeTracer represents an EVM.Logger which tracks and patches EVM execution state to enable extended
@@ -18,13 +22,16 @@ type cheatCodeTracer struct {
1822
callDepth uint64
1923

2024
// evm refers to the EVM instance last captured.
21-
evm *vm.EVM
25+
evmContext *tracing.VMContext
2226

2327
// callFrames represents per-call-frame data deployment information being captured by the tracer.
2428
callFrames []*cheatCodeTracerCallFrame
2529

2630
// results stores the tracer output after a transaction has concluded.
2731
results *cheatCodeTracerResults
32+
33+
// nativeTracer is the underlying tracer interface that the cheatcode tracer follows
34+
nativeTracer *TestChainTracer
2835
}
2936

3037
// cheatCodeTracerCallFrame represents per-call-frame data traced by a cheatCodeTracer.
@@ -57,13 +64,14 @@ type cheatCodeTracerCallFrame struct {
5764
// vmOp describes the current call frame's last instruction executed.
5865
vmOp vm.OpCode
5966
// vmScope describes the current call frame's scope context.
60-
vmScope *vm.ScopeContext
67+
vmScope tracing.OpContext
6168
// vmReturnData describes the current call frame's return data (set on exit).
6269
vmReturnData []byte
6370
// vmErr describes the current call frame's returned error (set on exit), nil if no error.
6471
vmErr error
6572
}
6673

74+
// cheatCodeTracerResults holds the hooks that need to be executed when the chain reverts.
6775
type cheatCodeTracerResults struct {
6876
// onChainRevertHooks describes hooks which are to be executed when the chain reverts.
6977
onChainRevertHooks types.GenericHookFuncs
@@ -72,9 +80,25 @@ type cheatCodeTracerResults struct {
7280
// newCheatCodeTracer creates a cheatCodeTracer and returns it.
7381
func newCheatCodeTracer() *cheatCodeTracer {
7482
tracer := &cheatCodeTracer{}
83+
innerTracer := &tracers.Tracer{
84+
Hooks: &tracing.Hooks{
85+
OnTxStart: tracer.OnTxStart,
86+
OnTxEnd: tracer.OnTxEnd,
87+
OnEnter: tracer.OnEnter,
88+
OnExit: tracer.OnExit,
89+
OnOpcode: tracer.OnOpcode,
90+
},
91+
}
92+
tracer.nativeTracer = &TestChainTracer{Tracer: innerTracer, CaptureTxEndSetAdditionalResults: tracer.CaptureTxEndSetAdditionalResults}
93+
7594
return tracer
7695
}
7796

97+
// NativeTracer returns the underlying TestChainTracer.
98+
func (t *cheatCodeTracer) NativeTracer() *TestChainTracer {
99+
return t.nativeTracer
100+
}
101+
78102
// bindToChain is called by the TestChain which created the tracer to set its reference.
79103
// Note: This is done because of the cheat code system's dependency on the genesis block, as well as chain's dependency
80104
// on it, which prevents the chain being set in the tracer on initialization.
@@ -98,115 +122,105 @@ func (t *cheatCodeTracer) CurrentCallFrame() *cheatCodeTracerCallFrame {
98122
return t.callFrames[t.callDepth]
99123
}
100124

101-
// CaptureTxStart is called upon the start of transaction execution, as defined by vm.EVMLogger.
102-
func (t *cheatCodeTracer) CaptureTxStart(gasLimit uint64) {
125+
// OnTxStart is called upon the start of transaction execution, as defined by tracers.Tracer.
126+
func (t *cheatCodeTracer) OnTxStart(vm *tracing.VMContext, tx *coretypes.Transaction, from common.Address) {
103127
// Reset our capture state
104128
t.callDepth = 0
105129
t.callFrames = make([]*cheatCodeTracerCallFrame, 0)
106130
t.results = &cheatCodeTracerResults{
107131
onChainRevertHooks: nil,
108132
}
133+
// Store our evm reference
134+
t.evmContext = vm
109135
}
110136

111-
// CaptureTxEnd is called upon the end of transaction execution, as defined by vm.EVMLogger.
112-
func (t *cheatCodeTracer) CaptureTxEnd(restGas uint64) {
137+
// OnTxEnd is called upon the end of transaction execution, as defined by tracers.Tracer
138+
func (t *cheatCodeTracer) OnTxEnd(*coretypes.Receipt, error) {
113139

114140
}
115141

116-
// CaptureStart initializes the tracing operation for the top of a call frame, as defined by vm.EVMLogger.
117-
func (t *cheatCodeTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
118-
// Store our evm reference
119-
t.evm = env
142+
// OnEnter initializes the tracing operation for the top of a call frame, as defined by tracers.Tracer.
143+
func (t *cheatCodeTracer) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
144+
// Check to see if this is the top level call frame
145+
isTopLevelFrame := depth == 0
146+
var callFrameData *cheatCodeTracerCallFrame
147+
if isTopLevelFrame {
148+
// Create our call frame struct to track data for this initial entry call frame.
149+
callFrameData = &cheatCodeTracerCallFrame{}
150+
} else {
151+
// We haven't updated our call depth yet, so obtain the "previous" call frame (current for now)
152+
previousCallFrame := t.CurrentCallFrame()
153+
154+
// Create our call frame struct to track data for this initial entry call frame.
155+
// We forward our "next frame hooks" to this frame, then clear them from the previous frame.
156+
callFrameData = &cheatCodeTracerCallFrame{
157+
onFrameExitRestoreHooks: previousCallFrame.onNextFrameExitRestoreHooks,
158+
}
159+
previousCallFrame.onNextFrameExitRestoreHooks = nil
160+
161+
// Increase our call depth now that we're entering a new call frame.
162+
t.callDepth++
163+
}
120164

121-
// Create our call frame struct to track data for this initial entry call frame.
122-
callFrameData := &cheatCodeTracerCallFrame{}
165+
// Append our new call frame
123166
t.callFrames = append(t.callFrames, callFrameData)
167+
168+
// Note: We do not execute events for "next frame enter" here, as we do not yet have scope information.
169+
// Those events are executed when the first EVM instruction is executed in the new scope.
124170
}
125171

126-
// CaptureEnd is called after a call to finalize tracing completes for the top of a call frame, as defined by vm.EVMLogger.
127-
func (t *cheatCodeTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
172+
// OnExit is called after a call to finalize tracing completes for the top of a call frame, as defined by tracers.Tracer.
173+
func (t *cheatCodeTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
128174
// Execute all current call frame exit hooks
129175
exitingCallFrame := t.callFrames[t.callDepth]
130176
exitingCallFrame.onFrameExitRestoreHooks.Execute(false, true)
131-
exitingCallFrame.onTopFrameExitRestoreHooks.Execute(false, true)
132177

133-
// If we didn't encounter an error in this call frame, we push our upward propagating revert events up one frame.
134-
if err == nil {
135-
// Store these revert hooks in our results.
136-
t.results.onChainRevertHooks = append(t.results.onChainRevertHooks, exitingCallFrame.onChainRevertRestoreHooks...)
178+
var parentCallFrame *cheatCodeTracerCallFrame
179+
if depth == 0 {
180+
// If this is the top-level call frame, execute all of its exit hooks
181+
exitingCallFrame.onTopFrameExitRestoreHooks.Execute(false, true)
137182
} else {
138-
// We hit an error, so a revert occurred before this tx was committed.
139-
exitingCallFrame.onChainRevertRestoreHooks.Execute(false, true)
183+
// If not, retrieve the parent call frame
184+
parentCallFrame = t.callFrames[t.callDepth-1]
140185
}
141186

142187
// We're exiting the current frame, so remove our frame data.
143188
t.callFrames = t.callFrames[:t.callDepth]
144-
}
145-
146-
// CaptureEnter is called upon entering of the call frame, as defined by vm.EVMLogger.
147-
func (t *cheatCodeTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
148-
// We haven't updated our call depth yet, so obtain the "previous" call frame (current for now)
149-
previousCallFrame := t.CurrentCallFrame()
150189

151-
// Increase our call depth now that we're entering a new call frame.
152-
t.callDepth++
153-
154-
// Create our call frame struct to track data for this initial entry call frame.
155-
// We forward our "next frame hooks" to this frame, then clear them from the previous frame.
156-
callFrameData := &cheatCodeTracerCallFrame{
157-
onFrameExitRestoreHooks: previousCallFrame.onNextFrameExitRestoreHooks,
158-
}
159-
previousCallFrame.onNextFrameExitRestoreHooks = nil
160-
t.callFrames = append(t.callFrames, callFrameData)
161-
162-
// Note: We do not execute events for "next frame enter" here, as we do not yet have scope information.
163-
// Those events are executed when the first EVM instruction is executed in the new scope.
164-
}
165-
166-
// CaptureExit is called upon exiting of the call frame, as defined by vm.EVMLogger.
167-
func (t *cheatCodeTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
168-
// Execute all current call frame exit hooks
169-
exitingCallFrame := t.callFrames[t.callDepth]
170-
exitingCallFrame.onFrameExitRestoreHooks.Execute(false, true)
171-
parentCallFrame := t.callFrames[t.callDepth-1]
172-
173-
// If we didn't encounter an error in this call frame, we push our upward propagating revert events up one frame.
174-
if err == nil {
190+
// If we didn't encounter an error in this call frame, we push our upward propagating restore events up one frame.
191+
if err == nil && depth == 0 {
192+
// Since this is the top call frame, we add the revert events to the results of the tracer and return early
193+
t.results.onChainRevertHooks = append(t.results.onChainRevertHooks, exitingCallFrame.onChainRevertRestoreHooks...)
194+
return
195+
} else if err == nil {
196+
// Propagate hooks up to the parent call frame
175197
parentCallFrame.onTopFrameExitRestoreHooks = append(parentCallFrame.onTopFrameExitRestoreHooks, exitingCallFrame.onTopFrameExitRestoreHooks...)
176198
parentCallFrame.onChainRevertRestoreHooks = append(parentCallFrame.onChainRevertRestoreHooks, exitingCallFrame.onChainRevertRestoreHooks...)
177199
} else {
178200
// We hit an error, so a revert occurred before this tx was committed.
179201
exitingCallFrame.onChainRevertRestoreHooks.Execute(false, true)
180202
}
181203

182-
// We're exiting the current frame, so remove our frame data.
183-
t.callFrames = t.callFrames[:t.callDepth]
184-
185204
// Decrease our call depth now that we've exited a call frame.
186205
t.callDepth--
187206
}
188207

189-
// CaptureState records data from an EVM state update, as defined by vm.EVMLogger.
190-
func (t *cheatCodeTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, vmErr error) {
208+
// OnOpcode records data from an EVM state update, as defined by tracers.Tracer.
209+
func (t *cheatCodeTracer) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
191210
// Set our current frame information.
192211
currentCallFrame := t.CurrentCallFrame()
193212
currentCallFrame.vmPc = pc
194-
currentCallFrame.vmOp = op
213+
currentCallFrame.vmOp = vm.OpCode(op)
195214
currentCallFrame.vmScope = scope
196215
currentCallFrame.vmReturnData = rData
197-
currentCallFrame.vmErr = vmErr
216+
currentCallFrame.vmErr = err
198217

199218
// We execute our entered next frame hooks here (from our previous call frame), as we now have scope information.
200219
if t.callDepth > 0 {
201220
t.callFrames[t.callDepth-1].onNextFrameEnterHooks.Execute(true, true)
202221
}
203222
}
204223

205-
// CaptureFault records an execution fault, as defined by vm.EVMLogger.
206-
func (t *cheatCodeTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
207-
208-
}
209-
210224
// CaptureTxEndSetAdditionalResults can be used to set additional results captured from execution tracing. If this
211225
// tracer is used during transaction execution (block creation), the results can later be queried from the block.
212226
// This method will only be called on the added tracer if it implements the extended TestChainTracer interface.

chain/config/config.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ type TestChainConfig struct {
1313

1414
// CheatCodeConfig indicates the configuration for EVM cheat codes to use.
1515
CheatCodeConfig CheatCodeConfig `json:"cheatCodes"`
16+
17+
// ContractAddressOverrides describes contracts that are going to be deployed at deterministic addresses
18+
ContractAddressOverrides map[common.Hash]common.Address `json:"contractAddressOverrides,omitempty"`
1619
}
1720

1821
// CheatCodeConfig describes any configuration options related to the use of vm extensions (a.k.a. cheat codes)
@@ -27,9 +30,16 @@ type CheatCodeConfig struct {
2730

2831
// GetVMConfigExtensions derives a vm.ConfigExtensions from the provided TestChainConfig.
2932
func (t *TestChainConfig) GetVMConfigExtensions() *vm.ConfigExtensions {
30-
// Obtain our cheat code precompiled contracts.
33+
// Create a copy of the contract address overrides that can be ephemerally updated by medusa-geth
34+
contractAddressOverrides := make(map[common.Hash]common.Address)
35+
for hash, addr := range t.ContractAddressOverrides {
36+
contractAddressOverrides[hash] = addr
37+
}
38+
39+
// Obtain our vm config extensions data structure
3140
return &vm.ConfigExtensions{
32-
OverrideCodeSizeCheck: t.CodeSizeCheckDisabled,
33-
AdditionalPrecompiles: make(map[common.Address]vm.PrecompiledContract),
41+
OverrideCodeSizeCheck: t.CodeSizeCheckDisabled,
42+
AdditionalPrecompiles: make(map[common.Address]vm.PrecompiledContract),
43+
ContractAddressOverrides: contractAddressOverrides,
3444
}
3545
}

chain/console_log_cheat_code_contract.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package chain
22

33
import (
4+
"strconv"
5+
46
"github.com/crytic/medusa/utils"
57
"github.com/ethereum/go-ethereum/accounts/abi"
68
"github.com/ethereum/go-ethereum/common"
7-
"strconv"
89
)
910

1011
// ConsoleLogContractAddress is the address for the console.log precompile contract

0 commit comments

Comments
 (0)