re-integrated handlers with op codes 0xf2/return ..0xff/selfdestruct
This commit is contained in:
parent
7436e516fd
commit
1bb6ef43a1
|
@ -51,7 +51,9 @@ proc mkOpTable(select: Fork): array[Op,Vm2OpExec] {.compileTime.} =
|
||||||
result.importList(select, vm2OpExecDup, "Dup")
|
result.importList(select, vm2OpExecDup, "Dup")
|
||||||
result.importList(select, vm2OpExecSwap, "Swap")
|
result.importList(select, vm2OpExecSwap, "Swap")
|
||||||
result.importList(select, vm2OpExecLog, "Log")
|
result.importList(select, vm2OpExecLog, "Log")
|
||||||
result.importList(select, vm2OpExecSysOP, "SysOp")
|
#result.importList(select, vm2OpExecCreate, "Create")
|
||||||
|
#result.importList(select, vm2OpExecCall, "Call")
|
||||||
|
result.importList(select, vm2OpExecSysOp, "SysOp")
|
||||||
|
|
||||||
for op in Op:
|
for op in Op:
|
||||||
if select notin result[op].forks:
|
if select notin result[op].forks:
|
||||||
|
|
|
@ -59,6 +59,7 @@ else:
|
||||||
|
|
||||||
Computation* = ref object
|
Computation* = ref object
|
||||||
returnStack*: seq[int]
|
returnStack*: seq[int]
|
||||||
|
output*: seq[byte]
|
||||||
vmState*: BaseVMState
|
vmState*: BaseVMState
|
||||||
gasMeter*: GasMeter
|
gasMeter*: GasMeter
|
||||||
stack*: Stack
|
stack*: Stack
|
||||||
|
|
|
@ -47,7 +47,6 @@ else:
|
||||||
emvcStatic = 1
|
emvcStatic = 1
|
||||||
ColdAccountAccessCost = 2
|
ColdAccountAccessCost = 2
|
||||||
WarmStorageReadCost = 3
|
WarmStorageReadCost = 3
|
||||||
|
|
||||||
type
|
type
|
||||||
GasInt = int
|
GasInt = int
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,8 @@ else:
|
||||||
const
|
const
|
||||||
ColdSloadCost = 42
|
ColdSloadCost = 42
|
||||||
WarmStorageReadCost = 43
|
WarmStorageReadCost = 43
|
||||||
|
var
|
||||||
var blindGasCosts: array[Op,int]
|
blindGasCosts: array[Op,int]
|
||||||
|
|
||||||
# copied from stack.nim
|
# copied from stack.nim
|
||||||
macro genTupleType(len: static[int], elemType: untyped): untyped =
|
macro genTupleType(len: static[int], elemType: untyped): untyped =
|
||||||
|
|
|
@ -12,32 +12,260 @@
|
||||||
## ======================================
|
## ======================================
|
||||||
##
|
##
|
||||||
|
|
||||||
|
const
|
||||||
|
kludge {.intdefine.}: int = 0
|
||||||
|
breakCircularDependency {.used.} = kludge > 0
|
||||||
|
|
||||||
import
|
import
|
||||||
../op_codes, ./oph_defs, ../../../errors.nim
|
../../../errors,
|
||||||
|
./oph_defs,
|
||||||
|
./oph_helpers,
|
||||||
|
stint
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Kludge BEGIN
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
when not breakCircularDependency:
|
||||||
|
import
|
||||||
|
../../../db/accounts_cache,
|
||||||
|
../../stack,
|
||||||
|
../../v2computation,
|
||||||
|
../../v2memory,
|
||||||
|
../../v2state,
|
||||||
|
../../v2types,
|
||||||
|
../gas_meter,
|
||||||
|
../utils/v2utils_numeric,
|
||||||
|
../v2gas_costs,
|
||||||
|
eth/common
|
||||||
|
|
||||||
|
else:
|
||||||
|
import macros
|
||||||
|
|
||||||
|
type
|
||||||
|
GasInt = int
|
||||||
|
GasResult = tuple[gasCost, gasRefund: GasInt]
|
||||||
|
const
|
||||||
|
ColdAccountAccessCost = 42
|
||||||
|
var
|
||||||
|
blindGasCosts: array[Op,int]
|
||||||
|
blindAddress: EthAddress
|
||||||
|
blindGasResult: GasResult
|
||||||
|
|
||||||
|
# copied from stack.nim
|
||||||
|
macro genTupleType(len: static[int], elemType: untyped): untyped =
|
||||||
|
result = nnkTupleConstr.newNimNode()
|
||||||
|
for i in 0 ..< len: result.add(elemType)
|
||||||
|
|
||||||
|
# function stubs from stack.nim (to satisfy compiler logic)
|
||||||
|
proc popAddress(x: var Stack): EthAddress = blindAddress
|
||||||
|
proc popInt(x: var Stack, n: static[int]): auto =
|
||||||
|
var rc: genTupleType(n, UInt256)
|
||||||
|
return rc
|
||||||
|
|
||||||
|
# function stubs from v2computation.nim (to satisfy compiler logic)
|
||||||
|
proc gasCosts(c: Computation): array[Op,int] = blindGasCosts
|
||||||
|
proc setError(c: Computation, msg: string, burnsGas = false) = discard
|
||||||
|
proc selfDestruct(c: Computation, address: EthAddress) = discard
|
||||||
|
proc accountExists(c: Computation, address: EthAddress): bool = false
|
||||||
|
proc getBalance[T](c: Computation, address: T): Uint256 = 0.u256
|
||||||
|
|
||||||
|
# function stubs from v2utils_numeric.nim
|
||||||
|
func cleanMemRef(x: UInt256): int = 0
|
||||||
|
|
||||||
|
# function stubs from v2memory.nim
|
||||||
|
proc len(mem: Memory): int = 0
|
||||||
|
proc extend(mem: var Memory; startPos: Natural; size: Natural) = discard
|
||||||
|
proc read(mem: var Memory, startPos: Natural, size: Natural): seq[byte] = @[]
|
||||||
|
|
||||||
|
# function stubs from v2state.nim
|
||||||
|
template mutateStateDB(vmState: BaseVMState, body: untyped) =
|
||||||
|
block:
|
||||||
|
var db {.inject.} = vmState.accountDb
|
||||||
|
body
|
||||||
|
|
||||||
|
# function stubs from gas_meter.nim
|
||||||
|
proc consumeGas(gasMeter: var GasMeter; amount: int; reason: string) = discard
|
||||||
|
|
||||||
|
# stubs from v2gas_costs.nim
|
||||||
|
type GasParams = object
|
||||||
|
case kind*: Op
|
||||||
|
of SelfDestruct:
|
||||||
|
sd_condition: bool
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
proc c_handler(x: int; y: Uint256, z: GasParams): GasResult = blindGasResult
|
||||||
|
proc m_handler(x: int; curMemSize, memOffset, memLen: int64): int = 0
|
||||||
|
|
||||||
|
# function stubs from accounts_cache.nim:
|
||||||
|
func inAccessList[A,B](ac: A; address: B): bool = false
|
||||||
|
proc accessList[A,B](ac: var A; address: B) = discard
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Kludge END
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Private
|
# Private
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
const
|
const
|
||||||
invalidOp: Vm2OpFn =
|
returnOp: Vm2OpFn = proc(k: Vm2Ctx) =
|
||||||
proc(k: Vm2Ctx) {.gcsafe.} =
|
## 0xf3, Halt execution returning output data.
|
||||||
|
let (startPos, size) = k.cpt.stack.popInt(2)
|
||||||
|
|
||||||
|
let (pos, len) = (startPos.cleanMemRef, size.cleanMemRef)
|
||||||
|
k.cpt.gasMeter.consumeGas(
|
||||||
|
k.cpt.gasCosts[Return].m_handler(k.cpt.memory.len, pos, len),
|
||||||
|
reason = "RETURN")
|
||||||
|
k.cpt.memory.extend(pos, len)
|
||||||
|
k.cpt.output = k.cpt.memory.read(pos, len)
|
||||||
|
|
||||||
|
|
||||||
|
revertOp: Vm2OpFn = proc(k: Vm2Ctx) =
|
||||||
|
## 0xfd, Halt execution reverting state changes but returning data
|
||||||
|
## and remaining gas.
|
||||||
|
let (startPos, size) = k.cpt.stack.popInt(2)
|
||||||
|
|
||||||
|
let (pos, len) = (startPos.cleanMemRef, size.cleanMemRef)
|
||||||
|
k.cpt.gasMeter.consumeGas(
|
||||||
|
k.cpt.gasCosts[Revert].m_handler(k.cpt.memory.len, pos, len),
|
||||||
|
reason = "REVERT")
|
||||||
|
|
||||||
|
k.cpt.memory.extend(pos, len)
|
||||||
|
k.cpt.output = k.cpt.memory.read(pos, len)
|
||||||
|
# setError(msg, false) will signal cheap revert
|
||||||
|
k.cpt.setError("REVERT opcode executed", false)
|
||||||
|
|
||||||
|
|
||||||
|
invalidOp: Vm2OpFn = proc(k: Vm2Ctx) =
|
||||||
raise newException(InvalidInstruction,
|
raise newException(InvalidInstruction,
|
||||||
"Invalid instruction, received an opcode " &
|
"Invalid instruction, received an opcode " &
|
||||||
"not implemented in the current fork.")
|
"not implemented in the current fork.")
|
||||||
|
|
||||||
|
# -----------
|
||||||
|
|
||||||
|
selfDestructOp: Vm2OpFn = proc(k: Vm2Ctx) =
|
||||||
|
## 0xff, Halt execution and register account for later deletion.
|
||||||
|
let beneficiary = k.cpt.stack.popAddress()
|
||||||
|
k.cpt.selfDestruct(beneficiary)
|
||||||
|
|
||||||
|
|
||||||
|
selfDestructEIP150Op: Vm2OpFn = proc(k: Vm2Ctx) =
|
||||||
|
## selfDestructEip150 (auto generated comment)
|
||||||
|
let beneficiary = k.cpt.stack.popAddress()
|
||||||
|
|
||||||
|
let gasParams = GasParams(
|
||||||
|
kind: SelfDestruct,
|
||||||
|
sd_condition: not k.cpt.accountExists(beneficiary))
|
||||||
|
|
||||||
|
let gasCost =
|
||||||
|
k.cpt.gasCosts[SelfDestruct].c_handler(0.u256, gasParams).gasCost
|
||||||
|
k.cpt.gasMeter.consumeGas(
|
||||||
|
gasCost, reason = "SELFDESTRUCT EIP150")
|
||||||
|
k.cpt.selfDestruct(beneficiary)
|
||||||
|
|
||||||
|
|
||||||
|
selfDestructEip161Op: Vm2OpFn = proc(k: Vm2Ctx) =
|
||||||
|
## selfDestructEip161 (auto generated comment)
|
||||||
|
checkInStaticContext(k.cpt)
|
||||||
|
|
||||||
|
let
|
||||||
|
beneficiary = k.cpt.stack.popAddress()
|
||||||
|
isDead = not k.cpt.accountExists(beneficiary)
|
||||||
|
balance = k.cpt.getBalance(k.cpt.msg.contractAddress)
|
||||||
|
|
||||||
|
let gasParams = GasParams(
|
||||||
|
kind: SelfDestruct,
|
||||||
|
sd_condition: isDead and not balance.isZero)
|
||||||
|
|
||||||
|
let gasCost =
|
||||||
|
k.cpt.gasCosts[SelfDestruct].c_handler(0.u256, gasParams).gasCost
|
||||||
|
k.cpt.gasMeter.consumeGas(
|
||||||
|
gasCost, reason = "SELFDESTRUCT EIP161")
|
||||||
|
k.cpt.selfDestruct(beneficiary)
|
||||||
|
|
||||||
|
|
||||||
|
selfDestructEIP2929Op: Vm2OpFn = proc(k: Vm2Ctx) =
|
||||||
|
## selfDestructEIP2929 (auto generated comment)
|
||||||
|
checkInStaticContext(k.cpt)
|
||||||
|
|
||||||
|
let
|
||||||
|
beneficiary = k.cpt.stack.popAddress()
|
||||||
|
isDead = not k.cpt.accountExists(beneficiary)
|
||||||
|
balance = k.cpt.getBalance(k.cpt.msg.contractAddress)
|
||||||
|
|
||||||
|
let gasParams = GasParams(
|
||||||
|
kind: SelfDestruct,
|
||||||
|
sd_condition: isDead and not balance.isZero)
|
||||||
|
|
||||||
|
var gasCost =
|
||||||
|
k.cpt.gasCosts[SelfDestruct].c_handler(0.u256, gasParams).gasCost
|
||||||
|
|
||||||
|
k.cpt.vmState.mutateStateDB:
|
||||||
|
if not db.inAccessList(beneficiary):
|
||||||
|
db.accessList(beneficiary)
|
||||||
|
gasCost = gasCost + ColdAccountAccessCost
|
||||||
|
|
||||||
|
k.cpt.gasMeter.consumeGas(
|
||||||
|
gasCost, reason = "SELFDESTRUCT EIP161")
|
||||||
|
k.cpt.selfDestruct(beneficiary)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public, op exec table entries
|
# Public, op exec table entries
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
const
|
const
|
||||||
vm2OpExecSysOP*: seq[Vm2OpExec] = @[
|
vm2OpExecSysOp*: seq[Vm2OpExec] = @[
|
||||||
|
|
||||||
|
(opCode: Return, ## 0xf3, Halt execution returning output data.
|
||||||
|
forks: Vm2OpAllForks,
|
||||||
|
info: "Halt execution returning output data",
|
||||||
|
exec: (prep: vm2OpIgnore,
|
||||||
|
run: returnOp,
|
||||||
|
post: vm2OpIgnore)),
|
||||||
|
|
||||||
|
(opCode: Revert, ## 0xfd, Halt and revert state changes
|
||||||
|
forks: Vm2OpAllForks,
|
||||||
|
info: "Halt execution reverting state changes but returning data " &
|
||||||
|
"and remaining gas",
|
||||||
|
exec: (prep: vm2OpIgnore,
|
||||||
|
run: revertOp,
|
||||||
|
post: vm2OpIgnore)),
|
||||||
|
|
||||||
(opCode: Invalid, ## 0xfe, invalid instruction.
|
(opCode: Invalid, ## 0xfe, invalid instruction.
|
||||||
forks: Vm2OpAllForks,
|
forks: Vm2OpAllForks,
|
||||||
info: "Designated invalid instruction",
|
info: "Designated invalid instruction",
|
||||||
exec: (prep: vm2OpIgnore,
|
exec: (prep: vm2OpIgnore,
|
||||||
run: invalidOp,
|
run: invalidOp,
|
||||||
|
post: vm2OpIgnore)),
|
||||||
|
|
||||||
|
(opCode: SelfDestruct, ## 0xff, Halt execution, prep for later deletion
|
||||||
|
forks: Vm2OpAllForks - Vm2OpTangerineAndLater,
|
||||||
|
info: "Halt execution and register account for later deletion",
|
||||||
|
exec: (prep: vm2OpIgnore,
|
||||||
|
run: selfDestructOp,
|
||||||
|
post: vm2OpIgnore)),
|
||||||
|
|
||||||
|
(opCode: SelfDestruct, ## 0xff, EIP150: self destruct, Tangerine
|
||||||
|
forks: Vm2OpTangerineAndLater - Vm2OpSpuriousAndLater,
|
||||||
|
info: "EIP150: Halt execution and register account for later deletion",
|
||||||
|
exec: (prep: vm2OpIgnore,
|
||||||
|
run: selfDestructEIP150Op,
|
||||||
|
post: vm2OpIgnore)),
|
||||||
|
|
||||||
|
(opCode: SelfDestruct, ## 0xff, EIP161: self destruct, Spurious and later
|
||||||
|
forks: Vm2OpSpuriousAndLater - Vm2OpBerlinAndLater,
|
||||||
|
info: "EIP161: Halt execution and register account for later deletion",
|
||||||
|
exec: (prep: vm2OpIgnore,
|
||||||
|
run: selfDestructEIP161Op,
|
||||||
|
post: vm2OpIgnore)),
|
||||||
|
|
||||||
|
(opCode: SelfDestruct, ## 0xff, EIP2929: self destruct, Berlin and later
|
||||||
|
forks: Vm2OpBerlinAndLater,
|
||||||
|
info: "EIP2929: Halt execution and register account for later deletion",
|
||||||
|
exec: (prep: vm2OpIgnore,
|
||||||
|
run: selfDestructEIP2929Op,
|
||||||
post: vm2OpIgnore))]
|
post: vm2OpIgnore))]
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
strformat, times, sets, sequtils, options,
|
strformat, times, sets, options,
|
||||||
chronicles, stint, nimcrypto, eth/common,
|
chronicles, stint, nimcrypto, eth/common,
|
||||||
./utils/[macros_procs_opcodes, v2utils_numeric],
|
./utils/[macros_procs_opcodes, v2utils_numeric],
|
||||||
./gas_meter, ./v2gas_costs, ./v2opcode_values, ./v2forks,
|
./gas_meter, ./v2gas_costs, ./v2opcode_values, ./v2forks,
|
||||||
|
@ -24,56 +24,10 @@ logScope:
|
||||||
# ##################################
|
# ##################################
|
||||||
# Syntactic sugar
|
# Syntactic sugar
|
||||||
|
|
||||||
proc gasEip2929AccountCheck(c: Computation, address: EthAddress, prevCost = 0.GasInt) =
|
|
||||||
c.vmState.mutateStateDB:
|
|
||||||
let gasCost = if not db.inAccessList(address):
|
|
||||||
db.accessList(address)
|
|
||||||
ColdAccountAccessCost
|
|
||||||
else:
|
|
||||||
WarmStorageReadCost
|
|
||||||
|
|
||||||
c.gasMeter.consumeGas(gasCost - prevCost, reason = "gasEIP2929AccountCheck")
|
|
||||||
|
|
||||||
template push(x: typed) {.dirty.} =
|
template push(x: typed) {.dirty.} =
|
||||||
## Push an expression on the computation stack
|
## Push an expression on the computation stack
|
||||||
c.stack.push x
|
c.stack.push x
|
||||||
|
|
||||||
proc writePaddedResult(mem: var Memory,
|
|
||||||
data: openarray[byte],
|
|
||||||
memPos, dataPos, len: Natural,
|
|
||||||
paddingValue = 0.byte) =
|
|
||||||
|
|
||||||
mem.extend(memPos, len)
|
|
||||||
let dataEndPosition = dataPos.int64 + len - 1
|
|
||||||
let sourceBytes = data[min(dataPos, data.len) .. min(data.len - 1, dataEndPosition)]
|
|
||||||
mem.write(memPos, sourceBytes)
|
|
||||||
|
|
||||||
# Don't duplicate zero-padding of mem.extend
|
|
||||||
let paddingOffset = min(memPos + sourceBytes.len, mem.len)
|
|
||||||
let numPaddingBytes = min(mem.len - paddingOffset, len - sourceBytes.len)
|
|
||||||
if numPaddingBytes > 0:
|
|
||||||
# TODO: avoid unnecessary memory allocation
|
|
||||||
mem.write(paddingOffset, repeat(paddingValue, numPaddingBytes))
|
|
||||||
|
|
||||||
template sstoreNetGasMeteringImpl(c: Computation, slot, newValue: Uint256) =
|
|
||||||
let stateDB = c.vmState.readOnlyStateDB
|
|
||||||
let currentValue {.inject.} = c.getStorage(slot)
|
|
||||||
|
|
||||||
let
|
|
||||||
gasParam = GasParams(
|
|
||||||
kind: Op.Sstore,
|
|
||||||
s_currentValue: currentValue,
|
|
||||||
s_originalValue: stateDB.getCommittedStorage(c.msg.contractAddress, slot))
|
|
||||||
(gasCost, gasRefund) = c.gasCosts[Sstore].c_handler(newValue, gasParam)
|
|
||||||
|
|
||||||
c.gasMeter.consumeGas(gasCost, &"SSTORE EIP2200: {c.msg.contractAddress}[{slot}] -> {newValue} ({currentValue})")
|
|
||||||
|
|
||||||
if gasRefund != 0:
|
|
||||||
c.gasMeter.refundGas(gasRefund)
|
|
||||||
|
|
||||||
c.vmState.mutateStateDB:
|
|
||||||
db.setStorage(c.msg.contractAddress, slot, newValue)
|
|
||||||
|
|
||||||
# ##################################
|
# ##################################
|
||||||
# re-implemented OP handlers
|
# re-implemented OP handlers
|
||||||
|
|
||||||
|
@ -248,6 +202,14 @@ opHandler log1, Op.Log1
|
||||||
opHandler log2, Op.Log2
|
opHandler log2, Op.Log2
|
||||||
opHandler log3, Op.Log3
|
opHandler log3, Op.Log3
|
||||||
opHandler log4, Op.Log4
|
opHandler log4, Op.Log4
|
||||||
|
opHandler returnOp, Op.Return
|
||||||
|
opHandler revert, Op.Revert
|
||||||
|
opHandler invalidOp, Op.Invalid
|
||||||
|
|
||||||
|
opHandler selfDestruct, Op.SelfDestruct, FkFrontier
|
||||||
|
opHandler selfDestructEIP150, Op.SelfDestruct, FkTangerine
|
||||||
|
opHandler selfDestructEIP161, Op.SelfDestruct, FkSpurious
|
||||||
|
opHandler selfDestructEIP2929, Op.SelfDestruct
|
||||||
|
|
||||||
# ##########################################
|
# ##########################################
|
||||||
# f0s: System operations.
|
# f0s: System operations.
|
||||||
|
@ -490,84 +452,3 @@ genCall(call, Call)
|
||||||
genCall(callCode, CallCode)
|
genCall(callCode, CallCode)
|
||||||
genCall(delegateCall, DelegateCall)
|
genCall(delegateCall, DelegateCall)
|
||||||
genCall(staticCall, StaticCall)
|
genCall(staticCall, StaticCall)
|
||||||
|
|
||||||
op returnOp, inline = false, startPos, size:
|
|
||||||
## 0xf3, Halt execution returning output data.
|
|
||||||
let (pos, len) = (startPos.cleanMemRef, size.cleanMemRef)
|
|
||||||
|
|
||||||
c.gasMeter.consumeGas(
|
|
||||||
c.gasCosts[Return].m_handler(c.memory.len, pos, len),
|
|
||||||
reason = "RETURN"
|
|
||||||
)
|
|
||||||
|
|
||||||
c.memory.extend(pos, len)
|
|
||||||
c.output = c.memory.read(pos, len)
|
|
||||||
|
|
||||||
op revert, inline = false, startPos, size:
|
|
||||||
## 0xfd, Halt execution reverting state changes but returning data and remaining gas.
|
|
||||||
let (pos, len) = (startPos.cleanMemRef, size.cleanMemRef)
|
|
||||||
c.gasMeter.consumeGas(
|
|
||||||
c.gasCosts[Revert].m_handler(c.memory.len, pos, len),
|
|
||||||
reason = "REVERT"
|
|
||||||
)
|
|
||||||
|
|
||||||
c.memory.extend(pos, len)
|
|
||||||
c.output = c.memory.read(pos, len)
|
|
||||||
# setError(msg, false) will signal cheap revert
|
|
||||||
c.setError("REVERT opcode executed", false)
|
|
||||||
|
|
||||||
op selfDestruct, inline = false:
|
|
||||||
## 0xff Halt execution and register account for later deletion.
|
|
||||||
let beneficiary = c.stack.popAddress()
|
|
||||||
c.selfDestruct(beneficiary)
|
|
||||||
|
|
||||||
op selfDestructEip150, inline = false:
|
|
||||||
let beneficiary = c.stack.popAddress()
|
|
||||||
|
|
||||||
let gasParams = GasParams(kind: SelfDestruct,
|
|
||||||
sd_condition: not c.accountExists(beneficiary)
|
|
||||||
)
|
|
||||||
|
|
||||||
let gasCost = c.gasCosts[SelfDestruct].c_handler(0.u256, gasParams).gasCost
|
|
||||||
c.gasMeter.consumeGas(gasCost, reason = "SELFDESTRUCT EIP150")
|
|
||||||
c.selfDestruct(beneficiary)
|
|
||||||
|
|
||||||
op selfDestructEip161, inline = false:
|
|
||||||
checkInStaticContext(c)
|
|
||||||
|
|
||||||
let
|
|
||||||
beneficiary = c.stack.popAddress()
|
|
||||||
isDead = not c.accountExists(beneficiary)
|
|
||||||
balance = c.getBalance(c.msg.contractAddress)
|
|
||||||
|
|
||||||
let gasParams = GasParams(kind: SelfDestruct,
|
|
||||||
sd_condition: isDead and not balance.isZero
|
|
||||||
)
|
|
||||||
|
|
||||||
let gasCost = c.gasCosts[SelfDestruct].c_handler(0.u256, gasParams).gasCost
|
|
||||||
c.gasMeter.consumeGas(gasCost, reason = "SELFDESTRUCT EIP161")
|
|
||||||
c.selfDestruct(beneficiary)
|
|
||||||
|
|
||||||
# Constantinople's new opcodes
|
|
||||||
|
|
||||||
op selfDestructEIP2929, inline = false:
|
|
||||||
checkInStaticContext(c)
|
|
||||||
|
|
||||||
let
|
|
||||||
beneficiary = c.stack.popAddress()
|
|
||||||
isDead = not c.accountExists(beneficiary)
|
|
||||||
balance = c.getBalance(c.msg.contractAddress)
|
|
||||||
|
|
||||||
let gasParams = GasParams(kind: SelfDestruct,
|
|
||||||
sd_condition: isDead and not balance.isZero
|
|
||||||
)
|
|
||||||
|
|
||||||
var gasCost = c.gasCosts[SelfDestruct].c_handler(0.u256, gasParams).gasCost
|
|
||||||
|
|
||||||
c.vmState.mutateStateDB:
|
|
||||||
if not db.inAccessList(beneficiary):
|
|
||||||
db.accessList(beneficiary)
|
|
||||||
gasCost = gasCost + ColdAccountAccessCost
|
|
||||||
|
|
||||||
c.gasMeter.consumeGas(gasCost, reason = "SELFDESTRUCT EIP161")
|
|
||||||
c.selfDestruct(beneficiary)
|
|
||||||
|
|
Loading…
Reference in New Issue