core/vm: disable the value transfer in syscall

This commit is contained in:
Gary Rong 2026-02-03 14:48:42 +08:00
parent a5e6a157e5
commit 7663959956

View file

@ -250,13 +250,14 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
if evm.depth > int(params.CallCreateDepth) { if evm.depth > int(params.CallCreateDepth) {
return nil, gas, ErrDepth return nil, gas, ErrDepth
} }
// Fail if we're trying to transfer more than the available balance syscall := isSystemCall(caller)
if !value.IsZero() && !evm.Context.CanTransfer(evm.StateDB, caller, value) {
// Fail if we're trying to transfer more than the available balance.
if !syscall && !value.IsZero() && !evm.Context.CanTransfer(evm.StateDB, caller, value) {
return nil, gas, ErrInsufficientBalance return nil, gas, ErrInsufficientBalance
} }
snapshot := evm.StateDB.Snapshot() snapshot := evm.StateDB.Snapshot()
p, isPrecompile := evm.precompile(addr) p, isPrecompile := evm.precompile(addr)
if !evm.StateDB.Exist(addr) { if !evm.StateDB.Exist(addr) {
if !isPrecompile && evm.chainRules.IsEIP4762 && !isSystemCall(caller) { if !isPrecompile && evm.chainRules.IsEIP4762 && !isSystemCall(caller) {
// Add proof of absence to witness // Add proof of absence to witness
@ -280,8 +281,11 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
} }
evm.StateDB.CreateAccount(addr) evm.StateDB.CreateAccount(addr)
} }
evm.Context.Transfer(evm.StateDB, caller, addr, value) // Perform the value transfer in non-syscall mode. This is essential for zero-value
// transfers to ensure the clearing mechanism is applied.
if !syscall {
evm.Context.Transfer(evm.StateDB, caller, addr, value)
}
if isPrecompile { if isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
} else { } else {
@ -307,7 +311,6 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil { if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution) evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution)
} }
gas = 0 gas = 0
} }
// TODO: consider clearing up unused snapshots: // TODO: consider clearing up unused snapshots: