Skip to content

Commit dc8e5d6

Browse files
committed
make SELFDESTRUCT match spec
1 parent 3b928e9 commit dc8e5d6

File tree

1 file changed

+34
-24
lines changed

1 file changed

+34
-24
lines changed

src/Nethermind/Nethermind.Evm/Instructions/EvmInstructions.ControlFlow.cs

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)