@@ -203,10 +203,6 @@ private static EvmExceptionType InstructionSelfDestruct(VirtualMachine vm, ref E
203203 IReleaseSpec spec = vm . Spec ;
204204 IWorldState state = vm . WorldState ;
205205
206- // SELFDESTRUCT is forbidden during static calls.
207- if ( vmState . IsStatic )
208- goto StaticCallViolation ;
209-
210206 // If Shanghai DDoS protection is active, charge the appropriate gas cost.
211207 if ( spec . UseShanghaiDDosProtection )
212208 {
@@ -218,52 +214,66 @@ private static EvmExceptionType InstructionSelfDestruct(VirtualMachine vm, ref E
218214 if ( inheritor is null )
219215 goto StackUnderflow ;
220216
221- // Charge gas for account access; if insufficient, signal out-of-gas.
222- if ( ! EvmCalculations . ChargeAccountAccessGas ( ref gasAvailable , vm , inheritor , chargeForWarm : false ) )
223- goto OutOfGas ;
217+ ( vm . WorldState as TracedAccessWorldState ) ? . AddAccountRead ( inheritor ) ;
224218
225219 Address executingAccount = vmState . Env . ExecutingAccount ;
226- bool createInSameTx = vmState . AccessTracker . CreateList . Contains ( executingAccount ) ;
227- // Mark the executing account for destruction if allowed.
228- if ( ! spec . SelfdestructOnlyOnSameTransaction || createInSameTx )
229- vmState . AccessTracker . ToBeDestroyed ( executingAccount ) ;
230-
231- // Retrieve the current balance for transfer.
232- UInt256 result = state . GetBalance ( executingAccount ) ;
233- if ( vm . TxTracer . IsTracingActions )
234- vm . TxTracer . ReportSelfDestruct ( executingAccount , result , inheritor ) ;
220+ UInt256 ? result = null ;
235221
236- // For certain specs, charge gas if transferring to a dead account.
237- if ( spec . ClearEmptyAccountWhenTouched && ! result . IsZero && state . IsDeadAccount ( inheritor ) )
222+ // Post EIP-158 charge gas if transferring non-zero value to a dead account.
223+ if ( spec . ClearEmptyAccountWhenTouched && state . IsDeadAccount ( inheritor ) )
238224 {
239- if ( ! EvmCalculations . UpdateGas ( GasCostOf . NewAccount , ref gasAvailable ) )
240- goto OutOfGas ;
225+ // Retrieve the current balance for transfer.
226+ // Add executing account to BAL
227+ result = state . GetBalance ( executingAccount ) ;
228+ if ( ! result . Value . IsZero )
229+ {
230+ if ( ! EvmCalculations . UpdateGas ( GasCostOf . NewAccount , ref gasAvailable ) )
231+ goto OutOfGas ;
232+ }
241233 }
242234
243- // If account creation rules apply, ensure gas is charged for new accounts.
235+ // Charge gas for account access; if insufficient, signal out-of-gas.
236+ if ( ! EvmCalculations . ChargeAccountAccessGas ( ref gasAvailable , vm , inheritor , chargeForWarm : false ) )
237+ goto OutOfGas ;
238+
239+ // Pre EIP-158 charge gas if transferring to a non-existent account.
244240 bool inheritorAccountExists = state . AccountExists ( inheritor ) ;
245241 if ( ! spec . ClearEmptyAccountWhenTouched && ! inheritorAccountExists && spec . UseShanghaiDDosProtection )
246242 {
247243 if ( ! EvmCalculations . UpdateGas ( GasCostOf . NewAccount , ref gasAvailable ) )
248244 goto OutOfGas ;
249245 }
250246
247+ // SELFDESTRUCT is forbidden during static calls.
248+ if ( vmState . IsStatic )
249+ goto StaticCallViolation ;
250+
251+ // Retrieve the current balance for transfer.
252+ result ??= state . GetBalance ( executingAccount ) ;
253+ if ( vm . TxTracer . IsTracingActions )
254+ vm . TxTracer . ReportSelfDestruct ( executingAccount , result . Value , inheritor ) ;
255+
256+ bool createInSameTx = vmState . AccessTracker . CreateList . Contains ( executingAccount ) ;
257+ // Mark the executing account for destruction if allowed.
258+ if ( ! spec . SelfdestructOnlyOnSameTransaction || createInSameTx )
259+ vmState . AccessTracker . ToBeDestroyed ( executingAccount ) ;
260+
251261 // Create or update the inheritor account with the transferred balance.
252262 if ( ! inheritorAccountExists )
253263 {
254- state . CreateAccount ( inheritor , result ) ;
264+ state . CreateAccount ( inheritor , result . Value ) ;
255265 }
256266 else if ( ! inheritor . Equals ( executingAccount ) )
257267 {
258- state . AddToBalance ( inheritor , result , spec ) ;
268+ state . AddToBalance ( inheritor , result . Value , spec ) ;
259269 }
260270
261271 // Special handling when SELFDESTRUCT is limited to the same transaction.
262272 if ( spec . SelfdestructOnlyOnSameTransaction && ! createInSameTx && inheritor . Equals ( executingAccount ) )
263273 goto Stop ; // Avoid burning ETH if contract is not destroyed per EIP clarification
264274
265275 // Subtract the balance from the executing account.
266- state . SubtractFromBalance ( executingAccount , result , spec ) ;
276+ state . SubtractFromBalance ( executingAccount , result . Value , spec ) ;
267277
268278 // Jump forward to be unpredicted by the branch predictor.
269279 Stop :
0 commit comments