Skip to content
This repository was archived by the owner on Dec 16, 2025. It is now read-only.

Commit 834853b

Browse files
sync: coreth PR #1301: fix: block hash when overriding to block n+1 (#1814)
Co-authored-by: Arran Schlosberg <519948+ARR4N@users.noreply.github.com>
1 parent 8944a69 commit 834853b

File tree

3 files changed

+49
-10
lines changed

3 files changed

+49
-10
lines changed

eth/tracers/api.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"encoding/json"
3434
"errors"
3535
"fmt"
36+
"math/big"
3637
"os"
3738
"runtime"
3839
"sync"
@@ -959,17 +960,32 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
959960
}
960961
defer release()
961962

962-
vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
963+
h := block.Header()
964+
blockContext := core.NewEVMBlockContext(h, api.chainContext(ctx), nil)
963965

964966
// Apply the customization rules if required.
965967
if config != nil {
968+
if config.BlockOverrides != nil && config.BlockOverrides.Number.ToInt().Uint64() == h.Number.Uint64()+1 {
969+
// Overriding the block number to n+1 is a common way for wallets to
970+
// simulate transactions, however without the following fix, a contract
971+
// can assert it is being simulated by checking if blockhash(n) == 0x0 and
972+
// can behave differently during the simulation. (#32175 for more info)
973+
// --
974+
// Modify the parent hash and number so that downstream, blockContext's
975+
// GetHash function can correctly return n.
976+
h.ParentHash = h.Hash()
977+
h.Number.Add(h.Number, big.NewInt(1))
978+
}
966979
originalTime := block.Time()
967-
config.BlockOverrides.Apply(&vmctx)
980+
config.BlockOverrides.Apply(&blockContext)
968981
// Apply all relevant upgrades from [originalTime] to the block time set in the override.
969982
// Should be applied before the state overrides.
970-
blockContext := core.NewBlockContext(vmctx.BlockNumber, vmctx.Time)
971-
err = core.ApplyUpgrades(api.backend.ChainConfig(), &originalTime, blockContext, statedb)
972-
if err != nil {
983+
if err := core.ApplyUpgrades(
984+
api.backend.ChainConfig(),
985+
&originalTime,
986+
core.NewBlockContext(block.Number(), block.Time()),
987+
statedb,
988+
); err != nil {
973989
return nil, err
974990
}
975991

@@ -978,7 +994,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
978994
}
979995
}
980996
// Execute the trace
981-
msg, err := args.ToMessage(api.backend.RPCGasCap(), vmctx.BaseFee)
997+
msg, err := args.ToMessage(api.backend.RPCGasCap(), blockContext.BaseFee)
982998
if err != nil {
983999
return nil, err
9841000
}
@@ -987,7 +1003,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
9871003
if config != nil {
9881004
traceConfig = &config.TraceConfig
9891005
}
990-
return api.traceTx(ctx, msg, new(Context), vmctx, statedb, traceConfig)
1006+
return api.traceTx(ctx, msg, new(Context), blockContext, statedb, traceConfig)
9911007
}
9921008

9931009
// traceTx configures a new tracer according to the provided configuration, and

eth/tracers/api_extra_test.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,9 @@ func testTraceCallWithOverridesStateUpgrade(t *testing.T, scheme string) {
423423
expect: `{"gas":21000,"failed":true,"returnValue":"","structLogs":[]}`,
424424
},
425425
{
426+
// Test that state upgrades are NOT applied when only time is overridden.
427+
// Even though we override time to after the state upgrade, the upgrade
428+
// should not be applied because it uses the original block time.
426429
blockNumber: rpc.BlockNumber(activateStateUpgradeBlock - 1),
427430
call: ethapi.TransactionArgs{
428431
From: &accounts[2].addr,
@@ -431,11 +434,12 @@ func testTraceCallWithOverridesStateUpgrade(t *testing.T, scheme string) {
431434
},
432435
config: &TraceCallConfig{
433436
BlockOverrides: &ethapi.BlockOverrides{
434-
Time: (*hexutil.Uint64)(&fastForwardTime),
437+
Number: (*hexutil.Big)(big.NewInt(int64(activateStateUpgradeBlock - 1))),
438+
Time: (*hexutil.Uint64)(&fastForwardTime),
435439
},
436440
},
437-
expectErr: core.ErrInsufficientFunds,
438-
expect: `{"gas":21000,"failed":true,"returnValue":"","structLogs":[]}`,
441+
expectErr: nil,
442+
expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`,
439443
},
440444
}
441445
for i, testspec := range testSuite {

eth/tracers/api_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,25 @@ func testTracingWithOverrides(t *testing.T, scheme string) {
928928
},
929929
want: `{"gas":25288,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000055"}`,
930930
},
931+
{ // Override blocknumber with block n+1 and query a blockhash (resolves issue #32175)
932+
blockNumber: rpc.LatestBlockNumber,
933+
call: ethapi.TransactionArgs{
934+
From: &accounts[0].addr,
935+
Input: newRPCBytes([]byte{
936+
byte(vm.PUSH1), byte(genBlocks),
937+
byte(vm.BLOCKHASH),
938+
byte(vm.PUSH1), 0x00,
939+
byte(vm.MSTORE),
940+
byte(vm.PUSH1), 0x20,
941+
byte(vm.PUSH1), 0x00,
942+
byte(vm.RETURN),
943+
}),
944+
},
945+
config: &TraceCallConfig{
946+
BlockOverrides: &ethapi.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(int64(genBlocks + 1)))},
947+
},
948+
want: fmt.Sprintf(`{"gas":59592,"failed":false,"returnValue":"%x"}`, backend.chain.GetHeaderByNumber(uint64(genBlocks)).Hash()),
949+
},
931950
}
932951
for i, tc := range testSuite {
933952
result, err := api.TraceCall(context.Background(), tc.call, rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, tc.config)

0 commit comments

Comments
 (0)