Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core/{.,state,vm},miner,eth/tracers,tests: implement 7709 with a syscall flag #31036

Merged
merged 5 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from 4 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
23 changes: 13 additions & 10 deletions core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
if err != nil {
panic(err)
}
// Merge the tx-local access event into the "block-local" one, in order to collect
// all values, so that the witness can be built.
if b.statedb.GetTrie().IsVerkle() {
b.statedb.AccessEvents().Merge(evm.AccessEvents)
}
b.txs = append(b.txs, tx)
b.receipts = append(b.receipts, receipt)
if b.header.BlobGasUsed != nil {
Expand Down Expand Up @@ -379,7 +384,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
misc.ApplyDAOHardFork(statedb)
}

if config.IsPrague(b.header.Number, b.header.Time) {
if config.IsPrague(b.header.Number, b.header.Time) || config.IsVerkle(b.header.Number, b.header.Time) {
// EIP-2935
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
blockContext.Random = &common.Hash{} // enable post-merge instruction set
Expand Down Expand Up @@ -487,13 +492,11 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
// Save pre state for proof generation
// preState := statedb.Copy()

// Pre-execution system calls.
if config.IsPrague(b.header.Number, b.header.Time) {
// EIP-2935
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
ProcessParentBlockHash(b.header.ParentHash, evm)
}
// EIP-2935 / 7709
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
blockContext.Random = &common.Hash{} // enable post-merge instruction set
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the best way I found to force the rules to accept that this is a merged network, happy to get some input in here.

evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
ProcessParentBlockHash(b.header.ParentHash, evm)

// Execute any user modifications to the block.
if gen != nil {
Expand Down Expand Up @@ -561,7 +564,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
return cm.chain, cm.receipts, proofs, keyvals
}

func GenerateVerkleChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (ethdb.Database, []*types.Block, []types.Receipts, []*verkle.VerkleProof, []verkle.StateDiff) {
func GenerateVerkleChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (common.Hash, ethdb.Database, []*types.Block, []types.Receipts, []*verkle.VerkleProof, []verkle.StateDiff) {
db := rawdb.NewMemoryDatabase()
cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme)
cacheConfig.SnapshotLimit = 0
Expand All @@ -572,7 +575,7 @@ func GenerateVerkleChainWithGenesis(genesis *Genesis, engine consensus.Engine, n
panic(err)
}
blocks, receipts, proofs, keyvals := GenerateVerkleChain(genesis.Config, genesisBlock, engine, db, triedb, n, gen)
return db, blocks, receipts, proofs, keyvals
return genesisBlock.Hash(), db, blocks, receipts, proofs, keyvals
}

func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engine consensus.Engine) *types.Header {
Expand Down
4 changes: 4 additions & 0 deletions core/state/statedb_hooked.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ func (s *hookedStateDB) Witness() *stateless.Witness {
return s.inner.Witness()
}

func (s *hookedStateDB) AccessEvents() *AccessEvents {
return s.inner.AccessEvents()
}

func (s *hookedStateDB) SubBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
prev := s.inner.SubBalance(addr, amount, reason)
if s.hooks.OnBalanceChange != nil && !amount.IsZero() {
Expand Down
24 changes: 15 additions & 9 deletions core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
ProcessBeaconBlockRoot(*beaconRoot, evm)
}
if p.config.IsPrague(block.Number(), block.Time()) {
if p.config.IsPrague(block.Number(), block.Time()) || p.config.IsVerkle(block.Number(), block.Time()) {
Copy link
Member

Choose a reason for hiding this comment

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

The p.config.IsPrague will be true if chain is in Verkle, with the assumption forks are enabled in order.

It's unnecessary to add this condition here.

Copy link
Member Author

Choose a reason for hiding this comment

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

that is not the case on verkle testnets as long as all of the code has been merged.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah...

It's annoying I agree...

Copy link
Contributor

Choose a reason for hiding this comment

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

that is not the case on verkle testnets as long as all of the code has been merged.

I don't understand this. can you elaborate a bit?

Copy link
Member Author

Choose a reason for hiding this comment

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

because merging my branch into geth takes forever, there is a testnet that exists, that has verkle enabled but not prague. We want to support that testnet as a first step, to confirm what has been merged is working.

ProcessParentBlockHash(block.ParentHash(), evm)
}

Expand Down Expand Up @@ -155,6 +155,12 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB,
}
*usedGas += result.UsedGas

// Merge the tx-local access event into the "block-local" one, in order to collect
// all values, so that the witness can be built.
if statedb.GetTrie().IsVerkle() {
statedb.AccessEvents().Merge(evm.AccessEvents)
}

return MakeReceipt(evm, result, statedb, blockNumber, blockHash, tx, *usedGas, root), nil
}

Expand All @@ -181,12 +187,6 @@ func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, b
receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
}

// Merge the tx-local access event into the "block-local" one, in order to collect
// all values, so that the witness can be built.
if statedb.GetTrie().IsVerkle() {
statedb.AccessEvents().Merge(evm.AccessEvents)
}

// Set the receipt logs and create the bloom filter.
receipt.Logs = statedb.GetLogs(tx.Hash(), blockNumber.Uint64(), blockHash)
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
Expand Down Expand Up @@ -234,7 +234,7 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM) {
}

// ProcessParentBlockHash stores the parent block hash in the history storage contract
// as per EIP-2935.
// as per EIP-2935/7709.
func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) {
if tracer := evm.Config.Tracer; tracer != nil {
onSystemCallStart(tracer, evm.GetVMContext())
Expand All @@ -253,7 +253,13 @@ func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) {
}
evm.SetTxContext(NewEVMTxContext(msg))
evm.StateDB.AddAddressToAccessList(params.HistoryStorageAddress)
_, _, _ = evm.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
_, _, err := evm.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
if err != nil {
panic(err)
}
if evm.StateDB.AccessEvents() != nil {
evm.StateDB.AccessEvents().Merge(evm.AccessEvents)
}
evm.StateDB.Finalise(true)
}

Expand Down
54 changes: 31 additions & 23 deletions core/verkle_witness_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func TestProcessVerkle(t *testing.T) {
txCost1*2 + txCost2,
txCost1*2 + txCost2 + contractCreationCost + codeWithExtCodeCopyGas,
}
_, chain, _, proofs, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
_, _, chain, _, proofs, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
gen.SetPoS()

// TODO need to check that the tx cost provided is the exact amount used (no remaining left-over)
Expand Down Expand Up @@ -219,44 +219,51 @@ func TestProcessParentBlockHash(t *testing.T) {
// block 1 parent hash is 0x0100....
// block 2 parent hash is 0x0200....
// etc
checkBlockHashes := func(statedb *state.StateDB) {
checkBlockHashes := func(statedb *state.StateDB, isVerkle bool) {
statedb.SetNonce(params.HistoryStorageAddress, 1)
statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode)
// Process n blocks, from 1 .. num
var num = 2
for i := 1; i <= num; i++ {
header := &types.Header{ParentHash: common.Hash{byte(i)}, Number: big.NewInt(int64(i)), Difficulty: new(big.Int)}
vmContext := NewEVMBlockContext(header, nil, new(common.Address))
evm := vm.NewEVM(vmContext, statedb, params.MergedTestChainConfig, vm.Config{})
chainConfig := params.MergedTestChainConfig
if isVerkle {
chainConfig = testVerkleChainConfig
}
evm := vm.NewEVM(vmContext, statedb, chainConfig, vm.Config{})
ProcessParentBlockHash(header.ParentHash, evm)
}
// Read block hashes for block 0 .. num-1
for i := 0; i < num; i++ {
have, want := getContractStoredBlockHash(statedb, uint64(i)), common.Hash{byte(i + 1)}
have, want := getContractStoredBlockHash(statedb, uint64(i), isVerkle), common.Hash{byte(i + 1)}
if have != want {
t.Errorf("block %d, have parent hash %v, want %v", i, have, want)
t.Errorf("block %d, verkle=%v, have parent hash %v, want %v", i, isVerkle, have, want)
}
}
}
t.Run("MPT", func(t *testing.T) {
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
checkBlockHashes(statedb)
checkBlockHashes(statedb, false)
})
t.Run("Verkle", func(t *testing.T) {
db := rawdb.NewMemoryDatabase()
cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme)
cacheConfig.SnapshotLimit = 0
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
statedb, _ := state.New(types.EmptyVerkleHash, state.NewDatabase(triedb, nil))
checkBlockHashes(statedb)
checkBlockHashes(statedb, true)
})
}

// getContractStoredBlockHash is a utility method which reads the stored parent blockhash for block 'number'
func getContractStoredBlockHash(statedb *state.StateDB, number uint64) common.Hash {
func getContractStoredBlockHash(statedb *state.StateDB, number uint64, isVerkle bool) common.Hash {
ringIndex := number % params.HistoryServeWindow
var key common.Hash
binary.BigEndian.PutUint64(key[24:], ringIndex)
if isVerkle {
return statedb.GetState(params.HistoryStorageAddress, key)
}
return statedb.GetState(params.HistoryStorageAddress, key)
}

Expand All @@ -279,7 +286,7 @@ func TestProcessVerkleInvalidContractCreation(t *testing.T) {
//
// - The second block contains a single failing contract creation transaction,
// that fails right off the bat.
_, chain, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
genesisH, _, chain, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
gen.SetPoS()

if i == 0 {
Expand Down Expand Up @@ -364,8 +371,9 @@ func TestProcessVerkleInvalidContractCreation(t *testing.T) {
if stemStateDiff.SuffixDiffs[0].NewValue == nil {
t.Fatalf("nil new value in BLOCKHASH contract insert")
}
if *stemStateDiff.SuffixDiffs[0].NewValue != chain[0].Hash() {
t.Fatalf("invalid BLOCKHASH value: %x != %x", *stemStateDiff.SuffixDiffs[0].NewValue, chain[0].Hash())
if *stemStateDiff.SuffixDiffs[0].NewValue != genesisH {
// je sais pas pourquoi, le hash storé est faux. On dirait le empty code hash mais c'est un hasard
jwasinger marked this conversation as resolved.
Show resolved Hide resolved
gballet marked this conversation as resolved.
Show resolved Hide resolved
t.Fatalf("invalid BLOCKHASH value: %x != %x", *stemStateDiff.SuffixDiffs[0].NewValue, genesisH)
}
} else {
// For all other entries present in the witness, check that nothing beyond
Expand Down Expand Up @@ -393,8 +401,8 @@ func TestProcessVerkleInvalidContractCreation(t *testing.T) {
if stemStateDiff.SuffixDiffs[0].NewValue == nil {
t.Fatalf("missing post state value for BLOCKHASH contract at block #2")
}
if *stemStateDiff.SuffixDiffs[0].NewValue != common.HexToHash("0788c2c0f23aa07eb8bf76fe6c1ca9064a4821c1fd0af803913da488a58dba54") {
t.Fatalf("invalid post state value for BLOCKHASH contract at block #2: 0788c2c0f23aa07eb8bf76fe6c1ca9064a4821c1fd0af803913da488a58dba54 != %x", (*stemStateDiff.SuffixDiffs[0].NewValue)[:])
if *stemStateDiff.SuffixDiffs[0].NewValue != chain[0].Hash() {
t.Fatalf("invalid post state value for BLOCKHASH contract at block #2: %x != %x", chain[0].Hash(), (*stemStateDiff.SuffixDiffs[0].NewValue)[:])
}
} else if suffixDiff.Suffix > 4 {
t.Fatalf("invalid suffix diff found for %x in block #2: %d\n", stemStateDiff.Stem, suffixDiff.Suffix)
Expand Down Expand Up @@ -440,7 +448,7 @@ func TestProcessVerkleContractWithEmptyCode(t *testing.T) {
config.ChainID.SetUint64(69421)
gspec := verkleTestGenesis(&config)

_, chain, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
genesisH, _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
gen.SetPoS()
var tx types.Transaction
// a transaction that does some PUSH1n but returns a 0-sized contract
Expand Down Expand Up @@ -472,8 +480,8 @@ func TestProcessVerkleContractWithEmptyCode(t *testing.T) {
if stemStateDiff.SuffixDiffs[0].NewValue == nil {
t.Fatalf("nil new value in BLOCKHASH contract insert")
}
if *stemStateDiff.SuffixDiffs[0].NewValue != chain[0].Hash() {
t.Fatalf("invalid BLOCKHASH value: %x != %x", *stemStateDiff.SuffixDiffs[0].NewValue, chain[0].Hash())
if *stemStateDiff.SuffixDiffs[0].NewValue != genesisH {
t.Fatalf("invalid BLOCKHASH value: %x != %x", *stemStateDiff.SuffixDiffs[0].NewValue, genesisH)
}
} else {
for _, suffixDiff := range stemStateDiff.SuffixDiffs {
Expand Down Expand Up @@ -532,7 +540,7 @@ func TestProcessVerkleExtCodeHashOpcode(t *testing.T) {
}
extCodeHashContractAddr := crypto.CreateAddress(deployer, 1)

_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
_, _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
gen.SetPoS()

if i == 0 {
Expand Down Expand Up @@ -605,7 +613,7 @@ func TestProcessVerkleBalanceOpcode(t *testing.T) {
account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d")
gspec = verkleTestGenesis(&config)
)
_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
_, _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
gen.SetPoS()
txData := slices.Concat(
[]byte{byte(vm.PUSH20)},
Expand Down Expand Up @@ -686,7 +694,7 @@ func TestProcessVerkleSelfDestructInSeparateTx(t *testing.T) {
deployer := crypto.PubkeyToAddress(testKey.PublicKey)
contract := crypto.CreateAddress(deployer, 0)

_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
_, _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
gen.SetPoS()

if i == 0 {
Expand Down Expand Up @@ -794,7 +802,7 @@ func TestProcessVerkleSelfDestructInSameTx(t *testing.T) {
deployer := crypto.PubkeyToAddress(testKey.PublicKey)
contract := crypto.CreateAddress(deployer, 0)

_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
_, _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
gen.SetPoS()
tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0,
Value: big.NewInt(42),
Expand Down Expand Up @@ -897,7 +905,7 @@ func TestProcessVerkleSelfDestructInSeparateTxWithSelfBeneficiary(t *testing.T)
deployer := crypto.PubkeyToAddress(testKey.PublicKey)
contract := crypto.CreateAddress(deployer, 0)

_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
_, _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
gen.SetPoS()
if i == 0 {
// Create self-destruct contract, sending 42 wei.
Expand Down Expand Up @@ -977,7 +985,7 @@ func TestProcessVerkleSelfDestructInSameTxWithSelfBeneficiary(t *testing.T) {

selfDestructContract := []byte{byte(vm.ADDRESS), byte(vm.SELFDESTRUCT)}

_, _, _, _, stateDiffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
_, _, _, _, _, stateDiffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
gen.SetPoS()
tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0,
Value: big.NewInt(42),
Expand Down Expand Up @@ -1043,7 +1051,7 @@ func TestProcessVerkleSelfDestructInSameTxWithSelfBeneficiaryAndPrefundedAccount

selfDestructContract := []byte{byte(vm.ADDRESS), byte(vm.SELFDESTRUCT)}

_, _, _, _, stateDiffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
_, _, _, _, _, stateDiffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
gen.SetPoS()
tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0,
Value: big.NewInt(42),
Expand Down
1 change: 1 addition & 0 deletions core/vm/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type Contract struct {

// is the execution frame represented by this object a contract deployment
IsDeployment bool
IsSystemCall bool

Gas uint64
value *uint256.Int
Expand Down
14 changes: 8 additions & 6 deletions core/vm/eips.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,10 +345,12 @@ func opExtCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC
self: AccountRef(addr),
}
paddedCodeCopy, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(code, uint64CodeOffset, length.Uint64())
statelessGas := interpreter.evm.AccessEvents.CodeChunksRangeGas(addr, copyOffset, nonPaddedCopyLength, uint64(len(contract.Code)), false)
if !scope.Contract.UseGas(statelessGas, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) {
scope.Contract.Gas = 0
return nil, ErrOutOfGas
if !contract.IsSystemCall {
statelessGas := interpreter.evm.AccessEvents.CodeChunksRangeGas(addr, copyOffset, nonPaddedCopyLength, uint64(len(contract.Code)), false)
if !scope.Contract.UseGas(statelessGas, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) {
scope.Contract.Gas = 0
return nil, ErrOutOfGas
}
}
scope.Memory.Set(memOffset.Uint64(), length.Uint64(), paddedCodeCopy)

Expand All @@ -367,7 +369,7 @@ func opPush1EIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
if *pc < codeLen {
scope.Stack.push(integer.SetUint64(uint64(scope.Contract.Code[*pc])))

if !scope.Contract.IsDeployment && *pc%31 == 0 {
if !scope.Contract.IsDeployment && !scope.Contract.IsSystemCall && *pc%31 == 0 {
// touch next chunk if PUSH1 is at the boundary. if so, *pc has
// advanced past this boundary.
contractAddr := scope.Contract.Address()
Expand Down Expand Up @@ -397,7 +399,7 @@ func makePushEIP4762(size uint64, pushByteSize int) executionFunc {
)),
)

if !scope.Contract.IsDeployment {
if !scope.Contract.IsDeployment && !scope.Contract.IsSystemCall {
contractAddr := scope.Contract.Address()
statelessGas := interpreter.evm.AccessEvents.CodeChunksRangeGas(contractAddr, uint64(start), uint64(pushByteSize), uint64(len(scope.Contract.Code)), false)
if !scope.Contract.UseGas(statelessGas, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) {
Expand Down
9 changes: 7 additions & 2 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,12 @@ func (evm *EVM) Interpreter() *EVMInterpreter {
return evm.interpreter
}

func isSystemCall(caller ContractRef) bool {
return caller.Address() == params.SystemAddress
}

// Call executes the contract associated with the addr with the given input as
// parameters. It also handles any necessary value transfer required and takes
// parameters. It also handles any necessary value transfer required and takse
// the necessary steps to create accounts and reverses the state in case of an
// execution error or failed value transfer.
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) {
Expand All @@ -194,7 +198,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
p, isPrecompile := evm.precompile(addr)

if !evm.StateDB.Exist(addr) {
if !isPrecompile && evm.chainRules.IsEIP4762 {
if !isPrecompile && evm.chainRules.IsEIP4762 && !isSystemCall(caller) {
// add proof of absence to witness
wgas := evm.AccessEvents.AddAccount(addr, false)
if gas < wgas {
Expand Down Expand Up @@ -225,6 +229,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
// If the account has no code, we can abort here
// The depth-check is already done, and precompiles handled above
contract := NewContract(caller, AccountRef(addrCopy), value, gas)
contract.IsSystemCall = isSystemCall(caller)
contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), code)
ret, err = evm.interpreter.Run(contract, input, false)
gas = contract.Gas
Expand Down
Loading