diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs b/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs index b29fcf00088..ad34320f047 100644 --- a/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs +++ b/src/Nethermind/Nethermind.Evm.Benchmark/EvmBenchmarks.cs @@ -58,7 +58,7 @@ public void GlobalSetup() inputData: default ); - _evmState = new EvmState(long.MaxValue, _environment, ExecutionType.TRANSACTION, _stateProvider.TakeSnapshot()); + _evmState = EvmState.RentTopLevel(long.MaxValue, ExecutionType.TRANSACTION, _stateProvider.TakeSnapshot(), _environment, new StackAccessTracker()); } [Benchmark] diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs b/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs index 97d0d9e6cf8..942d06a4929 100644 --- a/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs +++ b/src/Nethermind/Nethermind.Evm.Benchmark/MultipleUnsignedOperations.cs @@ -91,7 +91,7 @@ public void GlobalSetup() inputData: default ); - _evmState = new EvmState(100_000_000L, _environment, ExecutionType.TRANSACTION, _stateProvider.TakeSnapshot()); + _evmState = EvmState.RentTopLevel(100_000_000L, ExecutionType.TRANSACTION, _stateProvider.TakeSnapshot(), _environment, new StackAccessTracker()); } [Benchmark] diff --git a/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs b/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs index b7b8d39945b..c299c991efa 100644 --- a/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs +++ b/src/Nethermind/Nethermind.Evm.Benchmark/StaticCallBenchmarks.cs @@ -102,7 +102,7 @@ public void GlobalSetup() inputData: default ); - _evmState = new EvmState(100_000_000L, _environment, ExecutionType.TRANSACTION, _stateProvider.TakeSnapshot()); + _evmState = EvmState.RentTopLevel(100_000_000L, ExecutionType.TRANSACTION, _stateProvider.TakeSnapshot(), _environment, new StackAccessTracker()); } [Benchmark(Baseline = true)] diff --git a/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs b/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs index e462d04c288..2a6c1f8cbf5 100644 --- a/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/EvmStateTests.cs @@ -216,25 +216,26 @@ public void Can_dispose_without_init() public void Can_dispose_after_init() { EvmState evmState = CreateEvmState(); - evmState.InitStacks(); + evmState.InitializeStacks(); evmState.Dispose(); } private static EvmState CreateEvmState(EvmState parentEvmState = null, bool isContinuation = false) => parentEvmState is null - ? new EvmState(10000, - new ExecutionEnvironment(), - ExecutionType.CALL, - Snapshot.Empty) - : new EvmState(10000, - new ExecutionEnvironment(), + ? EvmState.RentTopLevel(10000, ExecutionType.CALL, Snapshot.Empty, + new ExecutionEnvironment(), + new StackAccessTracker()) + : EvmState.RentFrame(10000, 0, 0, + ExecutionType.CALL, + false, false, - parentEvmState.AccessTracker, - false); + Snapshot.Empty, + new ExecutionEnvironment(), + parentEvmState.AccessTracker); public class Context { } } diff --git a/src/Nethermind/Nethermind.Evm/EvmState.cs b/src/Nethermind/Nethermind.Evm/EvmState.cs index feb1abdbc87..ead92e96c8a 100644 --- a/src/Nethermind/Nethermind.Evm/EvmState.cs +++ b/src/Nethermind/Nethermind.Evm/EvmState.cs @@ -2,196 +2,238 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Concurrent; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using Nethermind.Core; using Nethermind.State; -namespace Nethermind.Evm +namespace Nethermind.Evm; + +/// +/// State for EVM Calls +/// +[DebuggerDisplay("{ExecutionType} to {Env.ExecutingAccount}, G {GasAvailable} R {Refund} PC {ProgramCounter} OUT {OutputDestination}:{OutputLength}")] +public sealed class EvmState : IDisposable // TODO: rename to CallState { + private static readonly ConcurrentQueue _statePool = new(); + private static readonly StackPool _stackPool = new(); + + public byte[]? DataStack; + public int[]? ReturnStack; + + public long GasAvailable { get; set; } + internal long OutputDestination { get; private set; } // TODO: move to CallEnv + internal long OutputLength { get; private set; } // TODO: move to CallEnv + public long Refund { get; set; } + + public int DataStackHead; + + public int ReturnStackHead; + internal ExecutionType ExecutionType { get; private set; } // TODO: move to CallEnv + public int ProgramCounter { get; set; } + public bool IsTopLevel { get; private set; } // TODO: move to CallEnv + private bool _canRestore; + public bool IsStatic { get; private set; } // TODO: move to CallEnv + public bool IsContinuation { get; set; } // TODO: move to CallEnv + public bool IsCreateOnPreExistingAccount { get; private set; } // TODO: move to CallEnv + + private bool _isDisposed = true; + + private EvmPooledMemory _memory; + private Snapshot _snapshot; + private ExecutionEnvironment _env; + private StackAccessTracker _accessTracker; + +#if DEBUG + private StackTrace? _creationStackTrace; +#endif /// - /// State for EVM Calls + /// Rent a top level . /// - [DebuggerDisplay("{ExecutionType} to {Env.ExecutingAccount}, G {GasAvailable} R {Refund} PC {ProgramCounter} OUT {OutputDestination}:{OutputLength}")] - public class EvmState : IDisposable // TODO: rename to CallState + public static EvmState RentTopLevel( + long gasAvailable, + ExecutionType executionType, + in Snapshot snapshot, + in ExecutionEnvironment env, + in StackAccessTracker accessedItems) { - private static readonly StackPool _stackPool = new(); - - public byte[]? DataStack; - - public int[]? ReturnStack; - - public StackAccessTracker AccessTracker => _accessTracker; - - private readonly StackAccessTracker _accessTracker; - - public int DataStackHead = 0; - - public int ReturnStackHead = 0; - private bool _canRestore = true; - /// - /// Constructor for a top level . - /// - public EvmState( - long gasAvailable, - ExecutionEnvironment env, - ExecutionType executionType, - Snapshot snapshot, - in StackAccessTracker accessedItems) : this(gasAvailable, - env, - executionType, - true, - snapshot, - 0L, - 0L, - false, - accessedItems, - false) - { - } - /// - /// Constructor for a top level . - /// - public EvmState( - long gasAvailable, - ExecutionEnvironment env, - ExecutionType executionType, - Snapshot snapshot) : this(gasAvailable, - env, - executionType, - true, - snapshot, - 0L, - 0L, - false, - new StackAccessTracker(), - false) - { - } - /// - /// Constructor for a frame beneath top level. - /// - internal EvmState( - long gasAvailable, - ExecutionEnvironment env, - ExecutionType executionType, - Snapshot snapshot, - long outputDestination, - long outputLength, - bool isStatic, - in StackAccessTracker stateForAccessLists, - bool isCreateOnPreExistingAccount) : - this( - gasAvailable, - env, - executionType, - false, - snapshot, - outputDestination, - outputLength, - isStatic, - stateForAccessLists, - isCreateOnPreExistingAccount) - { + EvmState state = Rent(); + state.Initialize( + gasAvailable, + outputDestination: 0L, + outputLength: 0L, + executionType: executionType, + isTopLevel: true, + isStatic: false, + isCreateOnPreExistingAccount: false, + snapshot: snapshot, + env: env, + stateForAccessLists: accessedItems); + return state; + } - } - private EvmState( - long gasAvailable, - ExecutionEnvironment env, - ExecutionType executionType, - bool isTopLevel, - Snapshot snapshot, - long outputDestination, - long outputLength, - bool isStatic, - in StackAccessTracker stateForAccessLists, - bool isCreateOnPreExistingAccount) + /// + /// Constructor for a frame beneath top level. + /// + public static EvmState RentFrame( + long gasAvailable, + long outputDestination, + long outputLength, + ExecutionType executionType, + bool isStatic, + bool isCreateOnPreExistingAccount, + in Snapshot snapshot, + in ExecutionEnvironment env, + in StackAccessTracker stateForAccessLists) + { + EvmState state = Rent(); + + state.Initialize( + gasAvailable, + outputDestination, + outputLength, + executionType, + isTopLevel: false, + isStatic: isStatic, + isCreateOnPreExistingAccount: isCreateOnPreExistingAccount, + snapshot: snapshot, + env: env, + stateForAccessLists: stateForAccessLists); + + return state; + } + + private static EvmState Rent() => _statePool.TryDequeue(out EvmState state) ? state : new EvmState(); + + private void Initialize( + long gasAvailable, + long outputDestination, + long outputLength, + ExecutionType executionType, + bool isTopLevel, + bool isStatic, + bool isCreateOnPreExistingAccount, + in Snapshot snapshot, + in ExecutionEnvironment env, + in StackAccessTracker stateForAccessLists) + { + GasAvailable = gasAvailable; + OutputDestination = outputDestination; + OutputLength = outputLength; + Refund = 0; + DataStackHead = 0; + ReturnStackHead = 0; + ExecutionType = executionType; + ProgramCounter = 0; + IsTopLevel = isTopLevel; + _canRestore = !isTopLevel; + IsStatic = isStatic; + IsContinuation = false; + IsCreateOnPreExistingAccount = isCreateOnPreExistingAccount; + _snapshot = snapshot; + _env = env; + _accessTracker = new(stateForAccessLists); + if (executionType.IsAnyCreate()) { - GasAvailable = gasAvailable; - ExecutionType = executionType; - IsTopLevel = isTopLevel; - _canRestore = !isTopLevel; - Snapshot = snapshot; - Env = env; - OutputDestination = outputDestination; - OutputLength = outputLength; - IsStatic = isStatic; - IsContinuation = false; - IsCreateOnPreExistingAccount = isCreateOnPreExistingAccount; - _accessTracker = new(stateForAccessLists); - if (executionType.IsAnyCreate()) - { - _accessTracker.WasCreated(env.ExecutingAccount); - } - _accessTracker.TakeSnapshot(); + _accessTracker.WasCreated(env.ExecutingAccount); } + _accessTracker.TakeSnapshot(); - public Address From + // Should be disposed when being initialized + if (!_isDisposed) { - get - { - return ExecutionType switch - { - ExecutionType.STATICCALL or ExecutionType.CALL or ExecutionType.CALLCODE or ExecutionType.CREATE or ExecutionType.CREATE2 or ExecutionType.TRANSACTION => Env.Caller, - ExecutionType.DELEGATECALL => Env.ExecutingAccount, - _ => throw new ArgumentOutOfRangeException(), - }; - } + ThrowIfNotUninitialized(); } + // Mark revived + _isDisposed = false; - public long GasAvailable { get; set; } - public int ProgramCounter { get; set; } - public long Refund { get; set; } +#if DEBUG + _creationStackTrace = new(); +#endif - public Address To => Env.CodeSource ?? Env.ExecutingAccount; - internal bool IsPrecompile => Env.CodeInfo.IsPrecompile; - public readonly ExecutionEnvironment Env; + [DoesNotReturn] + [StackTraceHidden] + static void ThrowIfNotUninitialized() + { + throw new InvalidOperationException("Already in use"); + } + } - internal ExecutionType ExecutionType { get; } // TODO: move to CallEnv - public bool IsTopLevel { get; } // TODO: move to CallEnv - internal long OutputDestination { get; } // TODO: move to CallEnv - internal long OutputLength { get; } // TODO: move to CallEnv - public bool IsStatic { get; } // TODO: move to CallEnv - public bool IsContinuation { get; set; } // TODO: move to CallEnv - public bool IsCreateOnPreExistingAccount { get; } // TODO: move to CallEnv - public Snapshot Snapshot { get; } // TODO: move to CallEnv + public Address From => ExecutionType switch + { + ExecutionType.STATICCALL or ExecutionType.CALL or ExecutionType.CALLCODE or ExecutionType.CREATE + or ExecutionType.CREATE2 or ExecutionType.TRANSACTION => Env.Caller, + ExecutionType.DELEGATECALL => Env.ExecutingAccount, + _ => throw new ArgumentOutOfRangeException(), + }; + + public Address To => Env.CodeSource ?? Env.ExecutingAccount; + internal bool IsPrecompile => Env.CodeInfo.IsPrecompile; + public ref readonly StackAccessTracker AccessTracker => ref _accessTracker; + public ref readonly ExecutionEnvironment Env => ref _env; + public ref EvmPooledMemory Memory => ref _memory; // TODO: move to CallEnv + public ref readonly Snapshot Snapshot => ref _snapshot; // TODO: move to CallEnv + + public void Dispose() + { + // Shouldn't be called multiple times + Debug.Assert(!_isDisposed); - private EvmPooledMemory _memory; - public ref EvmPooledMemory Memory => ref _memory; // TODO: move to CallEnv + if (_isDisposed) return; - public void Dispose() + _isDisposed = true; + if (DataStack is not null) { - if (DataStack is not null) - { - // Only Dispose once - _stackPool.ReturnStacks(DataStack, ReturnStack!); - DataStack = null; - ReturnStack = null; - } - Restore(); // we are trying to restore when disposing - Memory.Dispose(); - Memory = default; + // Only return if initialized + _stackPool.ReturnStacks(DataStack, ReturnStack!); + DataStack = null; + ReturnStack = null; } - - public void InitStacks() + if (_canRestore) { - if (DataStack is null) - { - (DataStack, ReturnStack) = _stackPool.RentStacks(); - } + // if we didn't commit and we are not top level, then we need to restore and drop the changes done in this call + _accessTracker.Restore(); } + _memory.Dispose(); + // Blank refs to not hold against GC + _memory = default; + _accessTracker = default; + _env = default; + _snapshot = default; + + _statePool.Enqueue(this); + +#if DEBUG + GC.SuppressFinalize(this); +#endif + } - public void CommitToParent(EvmState parentState) +#if DEBUG + ~EvmState() + { + if (!_isDisposed) { - parentState.Refund += Refund; - _canRestore = false; // we can't restore if we committed + throw new InvalidOperationException($"{nameof(EvmState)} hasn't been disposed. Created {_creationStackTrace}"); } + } +#endif + + public void InitializeStacks() + { + ObjectDisposedException.ThrowIf(_isDisposed, this); - private void Restore() + if (DataStack is null) { - if (_canRestore) // if we didn't commit and we are not top level, then we need to restore and drop the changes done in this call - { - _accessTracker.Restore(); - } + (DataStack, ReturnStack) = _stackPool.RentStacks(); } } + + public void CommitToParent(EvmState parentState) + { + ObjectDisposedException.ThrowIf(_isDisposed, this); + + parentState.Refund += Refund; + _canRestore = false; // we can't restore if we committed + } } diff --git a/src/Nethermind/Nethermind.Evm/StackAccessTracker.cs b/src/Nethermind/Nethermind.Evm/StackAccessTracker.cs index 6de077bc191..df941be5596 100644 --- a/src/Nethermind/Nethermind.Evm/StackAccessTracker.cs +++ b/src/Nethermind/Nethermind.Evm/StackAccessTracker.cs @@ -1,102 +1,126 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections.Concurrent; using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Core.Eip2930; using Nethermind.Int256; -namespace Nethermind.Evm +namespace Nethermind.Evm; + +public struct StackAccessTracker : IDisposable { - public struct StackAccessTracker + public readonly IReadOnlySet
AccessedAddresses => _trackingState.AccessedAddresses; + public readonly IReadOnlySet AccessedStorageCells => _trackingState.AccessedStorageCells; + public readonly ICollection Logs => _trackingState.Logs; + public readonly IReadOnlySet
DestroyList => _trackingState.DestroyList; + public readonly IReadOnlySet CreateList => _trackingState.CreateList; + + private TrackingState _trackingState; + + private int _addressesSnapshots; + private int _storageKeysSnapshots; + private int _destroyListSnapshots; + private int _logsSnapshots; + + public StackAccessTracker(in StackAccessTracker accessTracker) { - public readonly IReadOnlySet
AccessedAddresses => _accessedAddresses; - public readonly IReadOnlySet AccessedStorageCells => _accessedStorageCells; - public readonly ICollection Logs => _logs; - public readonly IReadOnlySet
DestroyList => _destroyList; - public readonly IReadOnlySet CreateList => _createList; - private readonly JournalSet
_accessedAddresses; - private readonly JournalSet _accessedStorageCells; - private readonly JournalCollection _logs; - private readonly JournalSet
_destroyList; - private readonly HashSet _createList; - - private int _addressesSnapshots; - private int _storageKeysSnapshots; - private int _destroyListSnapshots; - private int _logsSnapshots; - - public StackAccessTracker(in StackAccessTracker accessTracker) - { - _accessedAddresses = accessTracker._accessedAddresses; - _accessedStorageCells = accessTracker._accessedStorageCells; - _logs = accessTracker._logs; - _destroyList = accessTracker._destroyList; - _createList = accessTracker._createList; - } + _trackingState = accessTracker._trackingState; + } - public StackAccessTracker() - { - _accessedAddresses = new(); - _accessedStorageCells = new(); - _logs = new(); - _destroyList = new(); - _createList = new(); - } - public readonly bool IsCold(Address? address) => !AccessedAddresses.Contains(address); + public StackAccessTracker() + { + _trackingState = TrackingState.RentState(); + } + public readonly bool IsCold(Address? address) => !_trackingState.AccessedAddresses.Contains(address); - public readonly bool IsCold(in StorageCell storageCell) => !_accessedStorageCells.Contains(storageCell); + public readonly bool IsCold(in StorageCell storageCell) => !_trackingState.AccessedStorageCells.Contains(storageCell); - public readonly void WarmUp(Address address) - { - _accessedAddresses.Add(address); - } + public readonly void WarmUp(Address address) + { + _trackingState.AccessedAddresses.Add(address); + } - public readonly void WarmUp(in StorageCell storageCell) - { - _accessedStorageCells.Add(storageCell); - } + public readonly void WarmUp(in StorageCell storageCell) + { + _trackingState.AccessedStorageCells.Add(storageCell); + } - public readonly void WarmUp(AccessList? accessList) + public readonly void WarmUp(AccessList? accessList) + { + if (accessList?.IsEmpty == false) { - if (accessList?.IsEmpty == false) + foreach ((Address address, AccessList.StorageKeysEnumerable storages) in accessList) { - foreach ((Address address, AccessList.StorageKeysEnumerable storages) in accessList) + _trackingState.AccessedAddresses.Add(address); + foreach (UInt256 storage in storages) { - _accessedAddresses.Add(address); - foreach (UInt256 storage in storages) - { - _accessedStorageCells.Add(new StorageCell(address, storage)); - } + _trackingState.AccessedStorageCells.Add(new StorageCell(address, storage)); } } } + } - public readonly void ToBeDestroyed(Address address) - { - _destroyList.Add(address); - } + public readonly void ToBeDestroyed(Address address) + { + _trackingState.DestroyList.Add(address); + } - public readonly void WasCreated(Address address) - { - _createList.Add(address); - } + public readonly void WasCreated(Address address) + { + _trackingState.CreateList.Add(address); + } + + public void TakeSnapshot() + { + _addressesSnapshots = _trackingState.AccessedAddresses.TakeSnapshot(); + _storageKeysSnapshots = _trackingState.AccessedStorageCells.TakeSnapshot(); + _destroyListSnapshots = _trackingState.DestroyList.TakeSnapshot(); + _logsSnapshots = _trackingState.Logs.TakeSnapshot(); + } + + public readonly void Restore() + { + _trackingState.Logs.Restore(_logsSnapshots); + _trackingState.DestroyList.Restore(_destroyListSnapshots); + _trackingState.AccessedAddresses.Restore(_addressesSnapshots); + _trackingState.AccessedStorageCells.Restore(_storageKeysSnapshots); + } + + public void Dispose() + { + TrackingState state = _trackingState; + _trackingState = null; + TrackingState.ResetAndReturn(state); + } - public void TakeSnapshot() + private class TrackingState + { + private static readonly ConcurrentQueue _trackerPool = new(); + public static TrackingState RentState() => _trackerPool.TryDequeue(out TrackingState tracker) ? tracker : new TrackingState(); + + public static void ResetAndReturn(TrackingState state) { - _addressesSnapshots = _accessedAddresses.TakeSnapshot(); - _storageKeysSnapshots = _accessedStorageCells.TakeSnapshot(); - _destroyListSnapshots = _destroyList.TakeSnapshot(); - _logsSnapshots = _logs.TakeSnapshot(); + state.Clear(); + _trackerPool.Enqueue(state); } - public readonly void Restore() + public JournalSet
AccessedAddresses { get; } = new(); + public JournalSet AccessedStorageCells { get; } = new(); + public JournalCollection Logs { get; } = new(); + public JournalSet
DestroyList { get; } = new(); + public HashSet CreateList { get; } = new(); + + private void Clear() { - _logs.Restore(_logsSnapshots); - _destroyList.Restore(_destroyListSnapshots); - _accessedAddresses.Restore(_addressesSnapshots); - _accessedStorageCells.Restore(_storageKeysSnapshots); + AccessedAddresses.Clear(); + AccessedStorageCells.Clear(); + Logs.Clear(); + DestroyList.Clear(); + CreateList.Clear(); } } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index ce3038cf504..9638f58ff7f 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -158,7 +158,9 @@ protected virtual TransactionResult Execute(Transaction tx, in BlockExecutionCon if (commit) WorldState.Commit(spec, tracer.IsTracingState ? tracer : NullTxTracer.Instance, commitStorageRoots: false); - StackAccessTracker accessTracker = new(); + // substate.Logs contains a reference to accessTracker.Logs so we can't Dispose until end of the method + using StackAccessTracker accessTracker = new(); + int delegationRefunds = ProcessDelegations(tx, spec, accessTracker); ExecutionEnvironment env = BuildExecutionEnvironment(tx, in blCtx, spec, effectiveGasPrice, _codeInfoRepository, accessTracker); @@ -618,11 +620,11 @@ protected virtual void ExecuteEvmCall( } } - using (EvmState state = new EvmState( + using (EvmState state = EvmState.RentTopLevel( unspentGas, - env, tx.IsContractCreation ? ExecutionType.CREATE : ExecutionType.TRANSACTION, snapshot, + env, accessedItems)) { diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index 88525f10b84..56149f85a78 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -647,7 +647,7 @@ private CallResult ExecuteCall(EvmState vmState, ReadOnlyM goto Empty; } - vmState.InitStacks(); + vmState.InitializeStacks(); EvmStack stack = new(vmState.DataStackHead, _txTracer, vmState.DataStack.AsSpan()); long gasAvailable = vmState.GasAvailable; @@ -2229,16 +2229,16 @@ private EvmExceptionType InstructionCall( } ExecutionType executionType = GetCallExecutionType(instruction, env.IsPostMerge()); - returnData = new EvmState( + returnData = EvmState.RentFrame( gasLimitUl, - callEnv, - executionType, - snapshot, outputOffset.ToLong(), outputLength.ToLong(), + executionType, instruction == Instruction.STATICCALL || vmState.IsStatic, - vmState.AccessTracker, - isCreateOnPreExistingAccount: false); + isCreateOnPreExistingAccount: false, + snapshot: snapshot, + env: callEnv, + stateForAccessLists: vmState.AccessTracker); return EvmExceptionType.None; @@ -2468,16 +2468,16 @@ private EvmExceptionType InstructionSelfDestruct(EvmState vmState, ref transferValue: value, value: value ); - EvmState callState = new( + EvmState callState = EvmState.RentFrame( callGas, - callEnv, - instruction == Instruction.CREATE2 ? ExecutionType.CREATE2 : ExecutionType.CREATE, - snapshot, 0L, 0L, + instruction == Instruction.CREATE2 ? ExecutionType.CREATE2 : ExecutionType.CREATE, vmState.IsStatic, - vmState.AccessTracker, - accountExists); + accountExists, + snapshot, + callEnv, + vmState.AccessTracker); return (EvmExceptionType.None, callState); }