Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 10 additions & 3 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
// about the transaction and calling mechanisms.
vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true})
gasPool := new(core.GasPool).AddGas(math.MaxUint64)
signer := types.MakeSigner(b.blockchain.Config(), head.Number)
signer := types.MakeSigner(b.blockchain.Config(), head.Number, head.Time)
l1DataFee, err := fees.EstimateL1DataFeeForMessage(msg, head.BaseFee, b.blockchain.Config(), signer, stateDB, head.Number)
if err != nil {
return nil, err
Expand All @@ -753,7 +753,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
panic("could not fetch parent")
}
// Check transaction validity
signer := types.MakeSigner(b.blockchain.Config(), block.Number())
signer := types.MakeSigner(b.blockchain.Config(), block.Number(), block.Time())
sender, err := types.Sender(signer, tx)
if err != nil {
panic(fmt.Errorf("invalid transaction: %v", err))
Expand Down Expand Up @@ -915,6 +915,9 @@ func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
func (m callMsg) Data() []byte { return m.CallMsg.Data }
func (m callMsg) AccessList() types.AccessList { return m.CallMsg.AccessList }
func (m callMsg) IsL1MessageTx() bool { return false }
func (m callMsg) SetCodeAuthorizations() []types.SetCodeAuthorization {
return m.CallMsg.AuthorizationList
}

// filterBackend implements filters.Backend to support filtering for logs without
// taking bloom-bits acceleration structures into account.
Expand Down Expand Up @@ -952,7 +955,11 @@ func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (typ
if number == nil {
return nil, nil
}
return rawdb.ReadReceipts(fb.db, hash, *number, fb.bc.Config()), nil
header := rawdb.ReadHeader(fb.db, hash, *number)
if header == nil {
return nil, nil
}
return rawdb.ReadReceipts(fb.db, hash, *number, header.Time, fb.bc.Config()), nil
}

func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
Expand Down
2 changes: 1 addition & 1 deletion accounts/external/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
switch tx.Type() {
case types.LegacyTxType, types.AccessListTxType:
args.GasPrice = (*hexutil.Big)(tx.GasPrice())
case types.DynamicFeeTxType:
case types.DynamicFeeTxType, types.SetCodeTxType:
args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
default:
Comment on lines +221 to 224
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

SetCodeTxType gas handling OK; also propagate AuthorizationList to signer args

Dynamic-fee handling for SetCode is good. But the authorization list is not forwarded to clef, risking data loss when signing SetCode txs.

@@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
-		accessList := tx.AccessList()
-		args.AccessList = &accessList
+		accessList := tx.AccessList()
+		args.AccessList = &accessList
+		// For EIP-7702 SetCodeTxType, forward authorizations to the external signer (requires apitypes support).
+		if tx.Type() == types.SetCodeTxType {
+			auth := tx.SetCodeAuthorizations()
+			if len(auth) > 0 {
+				args.AuthorizationList = &auth
+			}
+		}

Verification:


🏁 Script executed:

#!/bin/bash
# Check if apitypes.SendTxArgs supports AuthorizationList; if not, add it.
rg -nC2 'type\s+SendTxArgs\s+struct' signer/core/apitypes | sed -n '1,200p'
rg -n 'AuthorizationList' --type=go signer/core/apitypes

Length of output: 563


🏁 Script executed:

#!/bin/bash
# Extract the full SendTxArgs struct definition to verify AuthorizationList support
sed -n '/type SendTxArgs struct {/,/^}/p' signer/core/apitypes/types.go

Length of output: 1056


Add AuthorizationList to SendTxArgs and forward SetCode authorizations

The SendTxArgs struct in signer/core/apitypes/types.go doesn’t include an AuthorizationList field. Add it just above ChainID:

 type SendTxArgs struct {
     … 
     AccessList *types.AccessList    `json:"accessList,omitempty"`
+    // For EIP-7702 SetCode transactions
+    AuthorizationList *[]types.Authorization `json:"authorizationList,omitempty"`
     ChainID    *hexutil.Big         `json:"chainId,omitempty"`
 }

Then in accounts/external/backend.go inside SignTx, propagate the authorizations for SetCodeTxType:

     accessList := tx.AccessList()
     args.AccessList = &accessList
+    if tx.Type() == types.SetCodeTxType {
+        auth := tx.SetCodeAuthorizations()
+        if len(auth) > 0 {
+            args.AuthorizationList = &auth
+        }
+    }

This ensures the external signer (e.g., clef) receives the authorization list when signing SetCode transactions.

Expand Down
30 changes: 15 additions & 15 deletions cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/morph-l2/go-ethereum/core"
"github.com/morph-l2/go-ethereum/core/rawdb"
"github.com/morph-l2/go-ethereum/core/state"
"github.com/morph-l2/go-ethereum/core/tracing"
"github.com/morph-l2/go-ethereum/core/types"
"github.com/morph-l2/go-ethereum/core/vm"
"github.com/morph-l2/go-ethereum/crypto"
Expand Down Expand Up @@ -97,10 +98,7 @@ type rejectedTx struct {
}

// Apply applies a set of transactions to a pre-state
func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
txs types.Transactions, miningReward int64,
getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error)) (*state.StateDB, *ExecutionResult, error) {

func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, txs types.Transactions, miningReward int64) (*state.StateDB, *ExecutionResult, error) {
// Capture errors for BLOCKHASH operation, if we haven't been supplied the
// required blockhashes
var hashError error
Expand All @@ -117,7 +115,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
}
var (
statedb = MakePreState(rawdb.NewMemoryDatabase(), pre.Pre)
signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number))
signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp)
gaspool = new(core.GasPool)
blockHash = common.Hash{0x13, 0x37}
rejectedTxs []*rejectedTx
Expand Down Expand Up @@ -160,12 +158,6 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
continue
}
tracer, err := getTracerFn(txIndex, tx.Hash())
if err != nil {
return nil, nil, err
}
vmConfig.Tracer = tracer
vmConfig.Debug = (tracer != nil)
statedb.SetTxContext(tx.Hash(), txIndex)
txContext := core.NewEVMTxContext(msg)
snapshot := statedb.Snapshot()
Expand All @@ -178,6 +170,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
continue
}

if evm.Config.Tracer != nil && evm.Config.Tracer.OnTxStart != nil {
evm.Config.Tracer.OnTxStart(evm.GetVMContext(), tx, msg.From())
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
// (ret []byte, usedGas uint64, failed bool, err error)
msgResult, err := core.ApplyMessage(evm, msg, gaspool, l1DataFee)
if err != nil {
Expand Down Expand Up @@ -211,6 +206,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
}
receipt.TxHash = tx.Hash()
receipt.GasUsed = msgResult.UsedGas
receipt.L1Fee = msgResult.L1DataFee

// If the transaction created a contract, store the creation address in the receipt.
if msg.To() == nil {
Expand All @@ -225,6 +221,10 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
//receipt.BlockNumber
receipt.TransactionIndex = uint(txIndex)
receipts = append(receipts, receipt)

if evm.Config.Tracer != nil && evm.Config.Tracer.OnTxEnd != nil {
evm.Config.Tracer.OnTxEnd(receipt, nil)
}
}

txIndex++
Expand All @@ -250,9 +250,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
reward.Sub(reward, big.NewInt(0).SetUint64(ommer.Delta))
reward.Mul(reward, blockReward)
reward.Div(reward, big.NewInt(8))
statedb.AddBalance(ommer.Address, reward)
statedb.AddBalance(ommer.Address, reward, tracing.BalanceIncreaseRewardMineUncle)
}
statedb.AddBalance(pre.Env.Coinbase, minerReward)
statedb.AddBalance(pre.Env.Coinbase, minerReward, tracing.BalanceIncreaseRewardMineBlock)
}
// Commit block
root, err := statedb.Commit(chainConfig.IsEIP158(vmContext.BlockNumber))
Expand All @@ -279,8 +279,8 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB
statedb, _ := state.New(common.Hash{}, sdb, nil)
for addr, a := range accounts {
statedb.SetCode(addr, a.Code)
statedb.SetNonce(addr, a.Nonce)
statedb.SetBalance(addr, a.Balance)
statedb.SetNonce(addr, a.Nonce, tracing.NonceChangeGenesis)
statedb.SetBalance(addr, a.Balance, tracing.BalanceIncreaseGenesisBalance)
for k, v := range a.Storage {
statedb.SetState(addr, k, v)
}
Expand Down
152 changes: 152 additions & 0 deletions cmd/evm/internal/t8ntool/file_tracer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// Copyright 2024 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.

package t8ntool

import (
"encoding/json"
"fmt"
"io"
"math/big"
"os"
"path/filepath"

"github.com/morph-l2/go-ethereum/common"
"github.com/morph-l2/go-ethereum/core/tracing"
"github.com/morph-l2/go-ethereum/core/types"
"github.com/morph-l2/go-ethereum/eth/tracers"
"github.com/morph-l2/go-ethereum/log"
)

// fileWritingTracer wraps either a tracer or a logger. On tx start,
// it instantiates a tracer/logger, creates a new file to direct output to,
// and on tx end it closes the file.
type fileWritingTracer struct {
txIndex int // transaction counter
inner *tracing.Hooks // inner hooks
destination io.WriteCloser // the currently open file (if any)
baseDir string // baseDir to write output-files to
suffix string // suffix is the suffix to use when creating files

// for custom tracing
getResult func() (json.RawMessage, error)
}

func (l *fileWritingTracer) Write(p []byte) (n int, err error) {
if l.destination != nil {
return l.destination.Write(p)
}
log.Warn("Tracer wrote to non-existing output")
// It is tempting to return an error here, however, the json encoder
// will no retry writing to an io.Writer once it has returned an error once.
// Therefore, we must squash the error.
return n, nil
}
Comment on lines +48 to +57
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Return len(p) when dropping writes to avoid Writer contract ambiguity.

Returning 0, nil can confuse callers; signal that bytes were “accepted” even if ignored.

-  return n, nil
+  return len(p), nil
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (l *fileWritingTracer) Write(p []byte) (n int, err error) {
if l.destination != nil {
return l.destination.Write(p)
}
log.Warn("Tracer wrote to non-existing output")
// It is tempting to return an error here, however, the json encoder
// will no retry writing to an io.Writer once it has returned an error once.
// Therefore, we must squash the error.
return n, nil
}
func (l *fileWritingTracer) Write(p []byte) (n int, err error) {
if l.destination != nil {
return l.destination.Write(p)
}
log.Warn("Tracer wrote to non-existing output")
// It is tempting to return an error here, however, the json encoder
// will no retry writing to an io.Writer once it has returned an error once.
// Therefore, we must squash the error.
return len(p), nil
}
🤖 Prompt for AI Agents
In cmd/evm/internal/t8ntool/file_tracer.go around lines 48 to 57, the Write
method currently returns the zero-valued n when dropping writes which can
violate io.Writer expectations; change the return so it reports the number of
bytes accepted by returning len(p), nil (or set n = len(p) before returning)
when l.destination is nil to clearly signal the bytes were "accepted" even
though they are ignored.


// newFileWriter creates a set of hooks which wraps inner hooks (typically a logger),
// and writes the output to a file, one file per transaction.
func newFileWriter(baseDir string, innerFn func(out io.Writer) *tracing.Hooks) *tracing.Hooks {
t := &fileWritingTracer{
baseDir: baseDir,
suffix: "jsonl",
}
t.inner = innerFn(t) // instantiate the inner tracer
return t.hooks()
}

// newResultWriter creates a set of hooks wraps and invokes an underlying tracer,
// and writes the result (getResult-output) to file, one per transaction.
func newResultWriter(baseDir string, tracer *tracers.Tracer) *tracing.Hooks {
t := &fileWritingTracer{
baseDir: baseDir,
getResult: tracer.GetResult,
inner: tracer.Hooks,
suffix: "json",
}
return t.hooks()
}

// OnTxStart creates a new output-file specific for this transaction, and invokes
// the inner OnTxStart handler.
func (l *fileWritingTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
// Open a new file, or print a warning log if it's failed
fname := filepath.Join(l.baseDir, fmt.Sprintf("trace-%d-%v.%v", l.txIndex, tx.Hash().String(), l.suffix))
traceFile, err := os.Create(fname)
if err != nil {
log.Warn("Failed creating trace-file", "err", err)
} else {
log.Info("Created tracing-file", "path", fname)
l.destination = traceFile
}
Comment on lines +85 to +93
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Create baseDir before file create; minor filename formatting.

Ensure directory exists to avoid silent drops; use %s for hash.

- fname := filepath.Join(l.baseDir, fmt.Sprintf("trace-%d-%v.%v", l.txIndex, tx.Hash().String(), l.suffix))
- traceFile, err := os.Create(fname)
+ fname := filepath.Join(l.baseDir, fmt.Sprintf("trace-%d-%s.%s", l.txIndex, tx.Hash(), l.suffix))
+ if mkErr := os.MkdirAll(l.baseDir, 0o755); mkErr != nil {
+   log.Warn("Failed ensuring trace directory", "dir", l.baseDir, "err", mkErr)
+ }
+ traceFile, err := os.Create(fname)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Open a new file, or print a warning log if it's failed
fname := filepath.Join(l.baseDir, fmt.Sprintf("trace-%d-%v.%v", l.txIndex, tx.Hash().String(), l.suffix))
traceFile, err := os.Create(fname)
if err != nil {
log.Warn("Failed creating trace-file", "err", err)
} else {
log.Info("Created tracing-file", "path", fname)
l.destination = traceFile
}
// Open a new file, or print a warning log if it fails
fname := filepath.Join(l.baseDir, fmt.Sprintf("trace-%d-%s.%s", l.txIndex, tx.Hash(), l.suffix))
if mkErr := os.MkdirAll(l.baseDir, 0o755); mkErr != nil {
log.Warn("Failed ensuring trace directory", "dir", l.baseDir, "err", mkErr)
}
traceFile, err := os.Create(fname)
if err != nil {
log.Warn("Failed creating trace-file", "err", err)
} else {
log.Info("Created tracing-file", "path", fname)
l.destination = traceFile
}
🤖 Prompt for AI Agents
In cmd/evm/internal/t8ntool/file_tracer.go around lines 85 to 93, the code
creates a trace file without ensuring the baseDir exists and formats the
filename using %v for the tx hash; update it to: ensure l.baseDir exists by
calling os.MkdirAll(l.baseDir, 0o755) and handling its error before calling
os.Create, change fmt.Sprintf to use "%s" for tx.Hash().String(), and preserve
logging on both MkdirAll and os.Create failures so the trace isn't silently
dropped.

if l.inner != nil && l.inner.OnTxStart != nil {
l.inner.OnTxStart(env, tx, from)
}
}

// OnTxEnd writes result (if getResult exist), closes any currently open output-file,
// and invokes the inner OnTxEnd handler.
func (l *fileWritingTracer) OnTxEnd(receipt *types.Receipt, err error) {
if l.inner != nil && l.inner.OnTxEnd != nil {
l.inner.OnTxEnd(receipt, err)
}
if l.getResult != nil && l.destination != nil {
if result, err := l.getResult(); result != nil {
json.NewEncoder(l.destination).Encode(result)
} else {
log.Warn("Error obtaining tracer result", "err", err)
}
l.destination.Close()
l.destination = nil
}
l.txIndex++
}
Comment on lines +101 to +115
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Always close the per-tx file; current logic leaks FDs when getResult is nil.

When using newFileWriter (jsonl), getResult is nil, so the file never closes. This leaks descriptors and can truncate subsequent writes.

Apply this diff to always close and to handle result/encoding errors:

 func (l *fileWritingTracer) OnTxEnd(receipt *types.Receipt, err error) {
   if l.inner != nil && l.inner.OnTxEnd != nil {
     l.inner.OnTxEnd(receipt, err)
   }
-  if l.getResult != nil && l.destination != nil {
-    if result, err := l.getResult(); result != nil {
-      json.NewEncoder(l.destination).Encode(result)
-    } else {
-      log.Warn("Error obtaining tracer result", "err", err)
-    }
-    l.destination.Close()
-    l.destination = nil
-  }
+  if l.destination != nil {
+    if l.getResult != nil {
+      if result, rerr := l.getResult(); rerr != nil {
+        log.Warn("Error obtaining tracer result", "err", rerr)
+      } else if result != nil {
+        if encErr := json.NewEncoder(l.destination).Encode(result); encErr != nil {
+          log.Warn("Error writing tracer result", "err", encErr)
+        }
+      }
+    }
+    if cerr := l.destination.Close(); cerr != nil {
+      log.Warn("Failed closing trace-file", "err", cerr)
+    }
+    l.destination = nil
+  }
   l.txIndex++
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (l *fileWritingTracer) OnTxEnd(receipt *types.Receipt, err error) {
if l.inner != nil && l.inner.OnTxEnd != nil {
l.inner.OnTxEnd(receipt, err)
}
if l.getResult != nil && l.destination != nil {
if result, err := l.getResult(); result != nil {
json.NewEncoder(l.destination).Encode(result)
} else {
log.Warn("Error obtaining tracer result", "err", err)
}
l.destination.Close()
l.destination = nil
}
l.txIndex++
}
func (l *fileWritingTracer) OnTxEnd(receipt *types.Receipt, err error) {
if l.inner != nil && l.inner.OnTxEnd != nil {
l.inner.OnTxEnd(receipt, err)
}
if l.destination != nil {
if l.getResult != nil {
if result, rerr := l.getResult(); rerr != nil {
log.Warn("Error obtaining tracer result", "err", rerr)
} else if result != nil {
if encErr := json.NewEncoder(l.destination).Encode(result); encErr != nil {
log.Warn("Error writing tracer result", "err", encErr)
}
}
}
if cerr := l.destination.Close(); cerr != nil {
log.Warn("Failed closing trace-file", "err", cerr)
}
l.destination = nil
}
l.txIndex++
}
🤖 Prompt for AI Agents
In cmd/evm/internal/t8ntool/file_tracer.go around lines 101 to 115, the current
OnTxEnd logic skips closing the per-transaction file when getResult is nil
causing FD leaks; always close and nil out l.destination regardless of
getResult, and avoid shadowing the outer err variable. Modify the block so it:
1) checks l.destination != nil and defers or calls l.destination.Close() and
sets l.destination = nil immediately; 2) calls l.getResult() if non-nil and
captures its error into a new local variable name (not err) so it doesn’t shadow
the method parameter; 3) if a result is returned, attempt json.Encode and log
any encoding error; 4) if getResult returns nil or an error, log the error with
context. Ensure closing happens even when encoding or getResult fails.


func (l *fileWritingTracer) hooks() *tracing.Hooks {
return &tracing.Hooks{
OnTxStart: l.OnTxStart,
OnTxEnd: l.OnTxEnd,
OnEnter: func(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
if l.inner != nil && l.inner.OnEnter != nil {
l.inner.OnEnter(depth, typ, from, to, input, gas, value)
}
},
OnExit: func(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
if l.inner != nil && l.inner.OnExit != nil {
l.inner.OnExit(depth, output, gasUsed, err, reverted)
}
},
OnOpcode: func(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
if l.inner != nil && l.inner.OnOpcode != nil {
l.inner.OnOpcode(pc, op, gas, cost, scope, rData, depth, err)
}
},
OnFault: func(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, depth int, err error) {
if l.inner != nil && l.inner.OnFault != nil {
l.inner.OnFault(pc, op, gas, cost, scope, depth, err)
}
},
OnSystemCallStart: func() {
if l.inner != nil && l.inner.OnSystemCallStart != nil {
l.inner.OnSystemCallStart()
}
},
OnSystemCallEnd: func() {
if l.inner != nil && l.inner.OnSystemCallEnd != nil {
l.inner.OnSystemCallEnd()
}
},
}
Comment on lines +117 to +151
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Pass through all inner hooks; current wrapper drops many (GasChange, Block, State, etc.).**

Only a subset is forwarded, causing lost events when using this wrapper.

Would you like me to add passthroughs for the remaining hooks (OnGasChange, OnBlockchainInit, OnClose, OnBlockStart/End/Skipped/Genesis, OnSystemCallStartV2, OnBalanceChange, OnNonceChange/OnNonceChangeV2, OnCodeChange, OnStorageChange, OnLog, OnBlockHashRead)? I can provide a patch once you confirm desired coverage.

🤖 Prompt for AI Agents
In cmd/evm/internal/t8ntool/file_tracer.go around lines 117 to 151, the hooks
wrapper only forwards a subset of tracing.Hooks and drops many events
(GasChange, Blockchain/Block lifecycle hooks, State changes, SystemCallStartV2,
Balance/Nonce/Code/Storage changes, Log, BlockHashRead, OnClose, etc.); update
the hooks() function to passthrough every hook field from l.inner when non-nil
by adding forwarding lambdas for OnGasChange, OnBlockchainInit, OnClose,
OnBlockStart, OnBlockEnd, OnBlockSkipped, OnBlockGenesis, OnSystemCallStartV2,
OnBalanceChange, OnNonceChange, OnNonceChangeV2, OnCodeChange, OnStorageChange,
OnLog, OnBlockHashRead (and any other missing fields present on tracing.Hooks)
following the same pattern used for existing hooks so no events are dropped.

}
20 changes: 12 additions & 8 deletions cmd/evm/internal/t8ntool/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@ import (
var (
TraceFlag = cli.BoolFlag{
Name: "trace",
Usage: "Output full trace logs to files <txhash>.jsonl",
Usage: "Configures the use of the JSON opcode tracer. This tracer emits traces to files as trace-<txIndex>-<txHash>.jsonl",
}
TraceDisableMemoryFlag = cli.BoolTFlag{
Name: "trace.nomemory",
Usage: "Disable full memory dump in traces (deprecated)",
TraceTracerFlag = &cli.StringFlag{
Name: "trace.tracer",
Usage: "Configures the use of a custom tracer, e.g native or js tracers. Examples are callTracer and 4byteTracer. These tracers emit results into files as trace-<txIndex>-<txHash>.json",
}
TraceTracerConfigFlag = &cli.StringFlag{
Name: "trace.jsonconfig",
Usage: "The configurations for the custom tracer specified by --trace.tracer. If provided, must be in JSON format",
}
TraceEnableMemoryFlag = cli.BoolFlag{
Name: "trace.memory",
Expand All @@ -43,14 +47,14 @@ var (
Name: "trace.nostack",
Usage: "Disable stack output in traces",
}
TraceDisableReturnDataFlag = cli.BoolTFlag{
Name: "trace.noreturndata",
Usage: "Disable return data output in traces (deprecated)",
}
TraceEnableReturnDataFlag = cli.BoolFlag{
Name: "trace.returndata",
Usage: "Enable return data output in traces",
}
TraceEnableCallFramesFlag = &cli.BoolFlag{
Name: "trace.callframes",
Usage: "Enable call frames output in traces",
}
OutputBasedir = cli.StringFlag{
Name: "output.basedir",
Usage: "Specifies where output files are placed. Will be created if it does not exist.",
Expand Down
4 changes: 2 additions & 2 deletions cmd/evm/internal/t8ntool/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func Transaction(ctx *cli.Context) error {
return NewError(ErrorIO, errors.New("only rlp supported"))
}
}
signer := types.MakeSigner(chainConfig, new(big.Int))
signer := types.MakeSigner(chainConfig, new(big.Int), 0)
// We now have the transactions in 'body', which is supposed to be an
// rlp list of transactions
it, err := rlp.NewListIterator([]byte(body))
Expand All @@ -140,7 +140,7 @@ func Transaction(ctx *cli.Context) error {
r.Address = sender
}
// Check intrinsic gas
if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil,
if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil,
chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int)), chainConfig.IsShanghai(new(big.Int))); err != nil {
r.Error = err
results = append(results, r)
Expand Down
Loading