Skip to content

Commit 924247c

Browse files
Fix panic when execution tracing cheatcode contracts (#411)
* fix panic when execution tracing cheatcode contracts. * Update chain/test_chain.go Co-authored-by: alpharush <[email protected]> --------- Co-authored-by: alpharush <[email protected]>
1 parent b4d4c56 commit 924247c

File tree

7 files changed

+30
-34
lines changed

7 files changed

+30
-34
lines changed

chain/test_chain.go

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"github.com/crytic/medusa/chain/config"
1010
"github.com/ethereum/go-ethereum/core/rawdb"
1111
"github.com/ethereum/go-ethereum/core/tracing"
12-
"github.com/ethereum/go-ethereum/eth/tracers"
1312
"github.com/ethereum/go-ethereum/triedb"
1413
"github.com/ethereum/go-ethereum/triedb/hashdb"
1514
"github.com/holiman/uint256"
@@ -256,7 +255,7 @@ func (t *TestChain) Clone(onCreateFunc func(chain *TestChain) error) (*TestChain
256255
// Now add each transaction/message to it.
257256
messages := t.blocks[i].Messages
258257
for j := 0; j < len(messages); j++ {
259-
err = targetChain.PendingBlockAddTx(messages[j], nil)
258+
err = targetChain.PendingBlockAddTx(messages[j])
260259
if err != nil {
261260
return nil, err
262261
}
@@ -728,15 +727,7 @@ func (t *TestChain) PendingBlockCreateWithParameters(blockNumber uint64, blockTi
728727
// PendingBlockAddTx takes a message (internal txs) and adds it to the current pending block, updating the header
729728
// with relevant execution information. If a pending block was not created, an error is returned.
730729
// Returns an error if one occurred.
731-
func (t *TestChain) PendingBlockAddTx(message *core.Message, getTracerFn func(txIndex int, txHash common.Hash) *tracers.Tracer) error {
732-
// Caller can specify any tracer they wish to use for this transaction
733-
if getTracerFn == nil {
734-
// TODO: Figure out whether it is possible to identify _which_ transaction you want to trace (versus all)
735-
getTracerFn = func(txIndex int, txHash common.Hash) *tracers.Tracer {
736-
return t.transactionTracerRouter.NativeTracer().Tracer
737-
}
738-
}
739-
730+
func (t *TestChain) PendingBlockAddTx(message *core.Message, additionalTracers ...*TestChainTracer) error {
740731
// If we don't have a pending block, return an error
741732
if t.pendingBlock == nil {
742733
return errors.New("could not add tx to the chain's pending block because no pending block was created")
@@ -757,12 +748,20 @@ func (t *TestChain) PendingBlockAddTx(message *core.Message, getTracerFn func(tx
757748
ConfigExtensions: t.vmConfigExtensions,
758749
}
759750

760-
// Set the tracer to be used in the vm config
761-
tracer := getTracerFn(len(t.pendingBlock.Messages), tx.Hash())
762-
if tracer != nil {
763-
vmConfig.Tracer = tracer.Hooks
751+
// Figure out whether we need to attach any more tracers
752+
var extendedTracerRouter *TestChainTracerRouter
753+
if len(additionalTracers) > 0 {
754+
// If we have more tracers, extend the transaction tracer router's tracers with additional ones
755+
extendedTracerRouter = NewTestChainTracerRouter()
756+
extendedTracerRouter.AddTracer(t.transactionTracerRouter.NativeTracer())
757+
extendedTracerRouter.AddTracers(additionalTracers...)
758+
} else {
759+
extendedTracerRouter = t.transactionTracerRouter
764760
}
765761

762+
// Update the VM's tracer
763+
vmConfig.Tracer = extendedTracerRouter.NativeTracer().Tracer.Hooks
764+
766765
// Set tx context
767766
t.state.SetTxContext(tx.Hash(), len(t.pendingBlock.Messages))
768767

chain/test_chain_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ func TestChainDynamicDeployments(t *testing.T) {
260260
assert.NoError(t, err)
261261

262262
// Add our transaction to the block
263-
err = chain.PendingBlockAddTx(&msg, nil)
263+
err = chain.PendingBlockAddTx(&msg)
264264
assert.NoError(t, err)
265265

266266
// Commit the pending block to the chain, so it becomes the new head.
@@ -385,7 +385,7 @@ func TestChainDeploymentWithArgs(t *testing.T) {
385385
assert.NoError(t, err)
386386

387387
// Add our transaction to the block
388-
err = chain.PendingBlockAddTx(&msg, nil)
388+
err = chain.PendingBlockAddTx(&msg)
389389
assert.NoError(t, err)
390390

391391
// Commit the pending block to the chain, so it becomes the new head.
@@ -494,7 +494,7 @@ func TestChainCloning(t *testing.T) {
494494
assert.NoError(t, err)
495495

496496
// Add our transaction to the block
497-
err = chain.PendingBlockAddTx(&msg, nil)
497+
err = chain.PendingBlockAddTx(&msg)
498498
assert.NoError(t, err)
499499

500500
// Commit the pending block to the chain, so it becomes the new head.
@@ -588,7 +588,7 @@ func TestChainCallSequenceReplayMatchSimple(t *testing.T) {
588588
assert.NoError(t, err)
589589

590590
// Add our transaction to the block
591-
err = chain.PendingBlockAddTx(&msg, nil)
591+
err = chain.PendingBlockAddTx(&msg)
592592
assert.NoError(t, err)
593593

594594
// Commit the pending block to the chain, so it becomes the new head.
@@ -627,7 +627,7 @@ func TestChainCallSequenceReplayMatchSimple(t *testing.T) {
627627
_, err := recreatedChain.PendingBlockCreate()
628628
assert.NoError(t, err)
629629
for _, message := range chain.blocks[i].Messages {
630-
err = recreatedChain.PendingBlockAddTx(message, nil)
630+
err = recreatedChain.PendingBlockAddTx(message)
631631
assert.NoError(t, err)
632632
}
633633
err = recreatedChain.PendingBlockCommit()

fuzzing/calls/call_sequence_execution.go

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ import (
77
"github.com/crytic/medusa/fuzzing/contracts"
88
"github.com/crytic/medusa/fuzzing/executiontracer"
99
"github.com/crytic/medusa/utils"
10-
"github.com/ethereum/go-ethereum/common"
11-
"github.com/ethereum/go-ethereum/eth/tracers"
1210
)
1311

1412
// ExecuteCallSequenceFetchElementFunc describes a function that is called to obtain the next call sequence element to
@@ -28,7 +26,7 @@ type ExecuteCallSequenceExecutionCheckFunc func(currentExecutedSequence CallSequ
2826
// A "post element executed check" function is provided to check whether execution should stop after each element is
2927
// executed.
3028
// Returns the call sequence which was executed and an error if one occurs.
31-
func ExecuteCallSequenceIteratively(chain *chain.TestChain, fetchElementFunc ExecuteCallSequenceFetchElementFunc, executionCheckFunc ExecuteCallSequenceExecutionCheckFunc, getTracerFn func(txIndex int, txHash common.Hash) *tracers.Tracer) (CallSequence, error) {
29+
func ExecuteCallSequenceIteratively(chain *chain.TestChain, fetchElementFunc ExecuteCallSequenceFetchElementFunc, executionCheckFunc ExecuteCallSequenceExecutionCheckFunc, additionalTracers ...*chain.TestChainTracer) (CallSequence, error) {
3230
// If there is no fetch element function provided, throw an error
3331
if fetchElementFunc == nil {
3432
return nil, fmt.Errorf("could not execute call sequence on chain as the 'fetch element function' provided was nil")
@@ -90,7 +88,7 @@ func ExecuteCallSequenceIteratively(chain *chain.TestChain, fetchElementFunc Exe
9088
}
9189

9290
// Try to add our transaction to this block.
93-
err = chain.PendingBlockAddTx(callSequenceElement.Call.ToCoreMessage(), getTracerFn)
91+
err = chain.PendingBlockAddTx(callSequenceElement.Call.ToCoreMessage(), additionalTracers...)
9492

9593
if err != nil {
9694
// If we encountered a block gas limit error, this tx is too expensive to fit in this block.
@@ -168,17 +166,14 @@ func ExecuteCallSequence(chain *chain.TestChain, callSequence CallSequence) (Cal
168166
return nil, nil
169167
}
170168

171-
return ExecuteCallSequenceIteratively(chain, fetchElementFunc, nil, nil)
169+
return ExecuteCallSequenceIteratively(chain, fetchElementFunc, nil)
172170
}
173171

174172
// ExecuteCallSequenceWithTracer attaches an executiontracer.ExecutionTracer to ExecuteCallSequenceIteratively and attaches execution traces to the call sequence elements.
175173
func ExecuteCallSequenceWithExecutionTracer(testChain *chain.TestChain, contractDefinitions contracts.Contracts, callSequence CallSequence, verboseTracing bool) (CallSequence, error) {
176174
// Create a new execution tracer
177175
executionTracer := executiontracer.NewExecutionTracer(contractDefinitions, testChain.CheatCodeContracts())
178176
defer executionTracer.Close()
179-
getTracerFunc := func(txIndex int, txHash common.Hash) *tracers.Tracer {
180-
return executionTracer.NativeTracer().Tracer
181-
}
182177

183178
// Execute our sequence with a simple fetch operation provided to obtain each element.
184179
fetchElementFunc := func(currentIndex int) (*CallSequenceElement, error) {
@@ -188,8 +183,8 @@ func ExecuteCallSequenceWithExecutionTracer(testChain *chain.TestChain, contract
188183
return nil, nil
189184
}
190185

191-
// Execute the call sequence
192-
executedCallSeq, err := ExecuteCallSequenceIteratively(testChain, fetchElementFunc, nil, getTracerFunc)
186+
// Execute the call sequence and attach the execution tracer
187+
executedCallSeq, err := ExecuteCallSequenceIteratively(testChain, fetchElementFunc, nil, executionTracer.NativeTracer())
193188

194189
// By default, we only trace the last element in the call sequence.
195190
traceFrom := len(callSequence) - 1

fuzzing/corpus/corpus.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ func (c *Corpus) initializeSequences(sequenceFiles *corpusDirectory[calls.CallSe
210210
}
211211

212212
// Execute each call sequence, populating runtime data and collecting coverage data along the way.
213-
_, err = calls.ExecuteCallSequenceIteratively(testChain, fetchElementFunc, executionCheckFunc, nil)
213+
_, err = calls.ExecuteCallSequenceIteratively(testChain, fetchElementFunc, executionCheckFunc)
214214

215215
// If we failed to replay a sequence and measure coverage due to an unexpected error, report it.
216216
if err != nil {

fuzzing/executiontracer/execution_tracer.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ func (t *ExecutionTracer) OnTxStart(vm *tracing.VMContext, tx *coretypes.Transac
119119
t.trace = newExecutionTrace(t.contractDefinitions)
120120
t.currentCallFrame = nil
121121
t.onNextCaptureState = nil
122+
t.traceMap = make(map[common.Hash]*ExecutionTrace)
123+
122124
// Store our evm reference
123125
t.evmContext = vm
124126
}

fuzzing/fuzzer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ func chainSetupFromCompilations(fuzzer *Fuzzer, testChain *chain.TestChain) (*ex
463463
}
464464

465465
// Add our transaction to the block
466-
err = testChain.PendingBlockAddTx(msg.ToCoreMessage(), nil)
466+
err = testChain.PendingBlockAddTx(msg.ToCoreMessage())
467467
if err != nil {
468468
return nil, err
469469
}

fuzzing/fuzzer_worker.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ func (fw *FuzzerWorker) testNextCallSequence() (calls.CallSequence, []ShrinkCall
317317
}
318318

319319
// Execute our call sequence.
320-
testedCallSequence, err := calls.ExecuteCallSequenceIteratively(fw.chain, fetchElementFunc, executionCheckFunc, nil)
320+
testedCallSequence, err := calls.ExecuteCallSequenceIteratively(fw.chain, fetchElementFunc, executionCheckFunc)
321321

322322
// If we encountered an error, report it.
323323
if err != nil {
@@ -383,7 +383,7 @@ func (fw *FuzzerWorker) testShrunkenCallSequence(possibleShrunkSequence calls.Ca
383383
}
384384

385385
// Execute our call sequence.
386-
_, err = calls.ExecuteCallSequenceIteratively(fw.chain, fetchElementFunc, executionCheckFunc, nil)
386+
_, err = calls.ExecuteCallSequenceIteratively(fw.chain, fetchElementFunc, executionCheckFunc)
387387
if err != nil {
388388
return false, err
389389
}

0 commit comments

Comments
 (0)