diff --git a/eth/tracers/native/contract.go b/eth/tracers/native/contract.go index 361a84e84219e..d7260b8b1aed1 100644 --- a/eth/tracers/native/contract.go +++ b/eth/tracers/native/contract.go @@ -33,15 +33,14 @@ func init() { } type contractTracer struct { - Addrs map[string]string + Addrs []string config contractTracerConfig interrupt uint32 // Atomic flag to signal execution interruption reason error // Textual reason for the interruption } type contractTracerConfig struct { - OpCode string `json:"opCode"` // Target opcode to trace - WithByteCode bool `json:"withByteCode"` // If true, bytecode will be collected + OpCode string `json:"opCode"` // Target opcode to trace } // NewContractTracer returns a native go tracer which tracks the contracr was created @@ -53,7 +52,7 @@ func NewContractTracer(cfg json.RawMessage) (tracers.Tracer, error) { } } t := &contractTracer{ - Addrs: make(map[string]string, 1), + Addrs: make([]string, 1), config: config, } // handle invalid opcode case @@ -66,8 +65,8 @@ func NewContractTracer(cfg json.RawMessage) (tracers.Tracer, error) { } func (t *contractTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - if create { - validateAndStoreOpCode(t, input, to) + if create || t.config.OpCode == "CALL" { + t.Addrs = append(t.Addrs, addrToHex(to)) } } @@ -75,22 +74,27 @@ func (t *contractTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Durati } func (t *contractTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { -} - -func (t *contractTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) { -} - -func (t *contractTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { // Skip if tracing was interrupted if atomic.LoadUint32(&t.interrupt) > 0 { // TODO: env.Cancel() return } - if typ == vm.CREATE || typ == vm.CREATE2 { - validateAndStoreOpCode(t, input, to) + // If the OpCode is empty , exit early. + if t.config.OpCode == "" { + return + } + if op.String() == t.config.OpCode { + addr := scope.Contract.Address() + t.Addrs = append(t.Addrs, addrToHex(addr)) } } +func (t *contractTracer) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) { +} + +func (t *contractTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { +} + func (t *contractTracer) CaptureExit(output []byte, gasUsed uint64, err error) { } @@ -106,31 +110,3 @@ func (t *contractTracer) Stop(err error) { t.reason = err atomic.StoreUint32(&t.interrupt, 1) } - -func validateAndStoreOpCode(t *contractTracer, input []byte, to common.Address) { - // If the OpCode is not empty and doesn't match the input, exit early. - if t.config.OpCode != "" && !findOpcodes(input, vm.StringToOp(t.config.OpCode)) { - return - } - // If WithByteCode is true, store the input in the address mapping as hex. - if t.config.WithByteCode { - t.Addrs[addrToHex(to)] = bytesToHex(input) - } else { - t.Addrs[addrToHex(to)] = "" - } -} - -// Compare bytecode with the given opcode, skipping PUSH instructions. -func findOpcodes(bytecode []byte, opcode vm.OpCode) bool { - for i := 0; i < len(bytecode); { - op := vm.OpCode(bytecode[i]) - // Skip PUSH opcodes and their arguments - if op.IsPush() { - i += int(op - 95) // Directly calculate the number of bytes to skip - } else if op == opcode { - return true - } - i++ - } - return false -}