Skip to content

Commit 01fe1d7

Browse files
rjl493456442fjl
andauthored
core/vm: disable the value transfer in syscall (ethereum#33741)
In src/ethereum/forks/amsterdam/vm/interpreter.py:299-304, the caller address is only tracked for block level accessList when there's a value transfer: ```python if message.should_transfer_value and message.value != 0: # Track value transfer sender_balance = get_account(state, message.caller).balance recipient_balance = get_account(state, message.current_target).balance track_address(message.state_changes, message.caller) # Line 304 ``` Since system transactions have should_transfer_value=False and value=0, this condition is never met, so the caller (SYSTEM_ADDRESS) is not tracked. This condition is applied for the syscall in the geth implementation, aligning with the spec of EIP7928. --------- Co-authored-by: Felix Lange <fjl@twurst.com>
1 parent 3eed058 commit 01fe1d7

File tree

1 file changed

+10
-6
lines changed

1 file changed

+10
-6
lines changed

core/vm/evm.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -245,13 +245,14 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
245245
if evm.depth > int(params.CallCreateDepth) {
246246
return nil, gas, ErrDepth
247247
}
248-
// Fail if we're trying to transfer more than the available balance
249-
if !value.IsZero() && !evm.Context.CanTransfer(evm.StateDB, caller, value) {
248+
syscall := isSystemCall(caller)
249+
250+
// Fail if we're trying to transfer more than the available balance.
251+
if !syscall && !value.IsZero() && !evm.Context.CanTransfer(evm.StateDB, caller, value) {
250252
return nil, gas, ErrInsufficientBalance
251253
}
252254
snapshot := evm.StateDB.Snapshot()
253255
p, isPrecompile := evm.precompile(addr)
254-
255256
if !evm.StateDB.Exist(addr) {
256257
if !isPrecompile && evm.chainRules.IsEIP4762 && !isSystemCall(caller) {
257258
// Add proof of absence to witness
@@ -275,8 +276,12 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
275276
}
276277
evm.StateDB.CreateAccount(addr)
277278
}
278-
evm.Context.Transfer(evm.StateDB, caller, addr, value)
279-
279+
// Perform the value transfer only in non-syscall mode.
280+
// Calling this is required even for zero-value transfers,
281+
// to ensure the state clearing mechanism is applied.
282+
if !syscall {
283+
evm.Context.Transfer(evm.StateDB, caller, addr, value)
284+
}
280285
if isPrecompile {
281286
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
282287
} else {
@@ -302,7 +307,6 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
302307
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
303308
evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution)
304309
}
305-
306310
gas = 0
307311
}
308312
// TODO: consider clearing up unused snapshots:

0 commit comments

Comments
 (0)