diff --git a/eth/tracers/firehose.go b/eth/tracers/firehose.go index e0731efc4a..34b00e81c0 100644 --- a/eth/tracers/firehose.go +++ b/eth/tracers/firehose.go @@ -2274,9 +2274,17 @@ func (m Memory) GetPtr(offset, size int64) []byte { return nil } - if len(m) > int(offset) { + if len(m) >= (int(offset) + int(size)) { return m[offset : offset+size] } - return nil + // The EVM does memory expansion **after** notifying us about OnOpcode which we use + // to compute Keccak256 pre-images now. This creates problem when we want to retrieve + // the preimage data because the memory is not expanded yet but in the EVM is going to + // work because the memory is going to be expanded before the operation is actually + // executed so the memory will be of the correct size. + // + // In this situtation, we must pad with zeroes when the memory is not big enough. + reminder := m[offset:] + return append(reminder, make([]byte, int(size)-len(reminder))...) } diff --git a/eth/tracers/firehose_test.go b/eth/tracers/firehose_test.go index d703addd05..7961419e9f 100644 --- a/eth/tracers/firehose_test.go +++ b/eth/tracers/firehose_test.go @@ -468,3 +468,25 @@ func blockEvent(height uint64) tracing.BlockEvent { TD: b(1), } } + +func TestMemory_GetPtr(t *testing.T) { + type args struct { + offset int64 + size int64 + } + tests := []struct { + name string + m Memory + args args + want []byte + }{ + {"memory is just a bit too small", Memory([]byte{1, 2, 3}), args{0, 4}, []byte{1, 2, 3, 0}}, + {"memory is flushed with request", Memory([]byte{1, 2, 3, 4}), args{0, 4}, []byte{1, 2, 3, 4}}, + {"memory is just a bit too big", Memory([]byte{1, 2, 3, 4, 5}), args{0, 4}, []byte{1, 2, 3, 4}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.want, tt.m.GetPtr(tt.args.offset, tt.args.size)) + }) + } +}