re-integrated/added EIP2929 handlers

This commit is contained in:
Jordan Hrycaj 2021-04-15 17:42:19 +01:00 committed by zah
parent 716bd64419
commit 7436e516fd
6 changed files with 230 additions and 88 deletions

View File

@ -66,6 +66,7 @@ else:
msg*: Message msg*: Message
code*: CodeStream code*: CodeStream
returnData*: seq[byte] returnData*: seq[byte]
fork*: Fork
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Kludge END # Kludge END

View File

@ -19,6 +19,7 @@ const
import import
../../../errors, ../../../errors,
./oph_defs, ./oph_defs,
./oph_helpers,
sequtils, sequtils,
strformat, strformat,
stint stint
@ -35,13 +36,20 @@ when not breakCircularDependency:
../../v2memory, ../../v2memory,
../../v2state, ../../v2state,
../gas_meter, ../gas_meter,
../v2gas_costs,
../utils/v2utils_numeric, ../utils/v2utils_numeric,
eth/common eth/common
else: else:
import macros import macros
var blindGasCosts: array[Op,int] var
GasBalance = 0
GasExtCode = 42
GasExtCodeHash = 7
blindGasCosts: array[Op,int]
blindAddress: EthAddress
gasFees: array[Fork,array[0..123,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 =
@ -50,7 +58,7 @@ else:
# function stubs from stack.nim (to satisfy compiler logic) # function stubs from stack.nim (to satisfy compiler logic)
proc push[T](x: Stack; n: T) = discard proc push[T](x: Stack; n: T) = discard
proc popAddress(x: var Stack): UInt256 = 0.u256 proc popAddress(x: var Stack): EthAddress = blindAddress
proc popInt(x: var Stack, n: static[int]): auto = proc popInt(x: var Stack, n: static[int]): auto =
var rc: genTupleType(n, UInt256) var rc: genTupleType(n, UInt256)
return rc return rc
@ -62,6 +70,7 @@ else:
proc getCode[T](c: Computation, address: T): seq[byte] = @[] proc getCode[T](c: Computation, address: T): seq[byte] = @[]
proc getGasPrice(c: Computation): Uint256 = 0.u256 proc getGasPrice(c: Computation): Uint256 = 0.u256
proc getOrigin(c: Computation): Uint256 = 0.u256 proc getOrigin(c: Computation): Uint256 = 0.u256
proc getCodeHash[T](c: Computation, address: T): Uint256 = 0.u256
# function stubs from v2utils_numeric.nim # function stubs from v2utils_numeric.nim
func cleanMemRef(x: UInt256): int = 0 func cleanMemRef(x: UInt256): int = 0
@ -117,12 +126,25 @@ const
k.cpt.stack.push: k.cpt.stack.push:
k.cpt.msg.contractAddress k.cpt.msg.contractAddress
# ------------------
balanceOp: Vm2OpFn = proc (k: Vm2Ctx) = balanceOp: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x31, Get balance of the given account. ## 0x31, Get balance of the given account.
let address = k.cpt.stack.popAddress let address = k.cpt.stack.popAddress
k.cpt.stack.push: k.cpt.stack.push:
k.cpt.getBalance(address) k.cpt.getBalance(address)
balanceEIP2929Op: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x31, EIP292: Get balance of the given account for Berlin and later
let address = k.cpt.stack.popAddress()
k.cpt.gasEip2929AccountCheck(
address, gasFees[k.cpt.fork][GasBalance])
k.cpt.stack.push:
k.cpt.getBalance(address)
# ------------------
originOp: Vm2OpFn = proc (k: Vm2Ctx) = originOp: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x32, Get execution origination address. ## 0x32, Get execution origination address.
k.cpt.stack.push: k.cpt.stack.push:
@ -204,7 +226,9 @@ const
gasPriceOp: Vm2OpFn = proc (k: Vm2Ctx) = gasPriceOp: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x3A, Get price of gas in current environment. ## 0x3A, Get price of gas in current environment.
k.cpt.stack.push: k.cpt.stack.push:
k.cpt.getGasPrice k.cpt.getGasPrice()
# -----------
extCodeSizeOp: Vm2OpFn = proc (k: Vm2Ctx) = extCodeSizeOp: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x3b, Get size of an account's code ## 0x3b, Get size of an account's code
@ -212,6 +236,16 @@ const
k.cpt.stack.push: k.cpt.stack.push:
k.cpt.getCodeSize(address) k.cpt.getCodeSize(address)
extCodeSizeEIP2929Op: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x3b, Get size of an account's code
let address = k.cpt.stack.popAddress()
k.cpt.gasEip2929AccountCheck(
address, gasFees[k.cpt.fork][GasExtCode])
k.cpt.stack.push:
k.cpt.getCodeSize(address)
# -----------
extCodeCopyOp: Vm2OpFn = proc (k: Vm2Ctx) = extCodeCopyOp: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x3c, Copy an account's code to memory. ## 0x3c, Copy an account's code to memory.
@ -229,6 +263,25 @@ const
k.cpt.memory.writePaddedResult(codeBytes, memPos, codePos, len) k.cpt.memory.writePaddedResult(codeBytes, memPos, codePos, len)
extCodeCopyEIP2929Op: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x3c, Copy an account's code to memory.
let address = k.cpt.stack.popAddress()
let (memStartPos, codeStartPos, size) = k.cpt.stack.popInt(3)
let (memPos, codePos, len) = (memStartPos.cleanMemRef,
codeStartPos.cleanMemRef, size.cleanMemRef)
k.cpt.gasMeter.consumeGas(
k.cpt.gasCosts[ExtCodeCopy].m_handler(k.cpt.memory.len, memPos, len),
reason = "ExtCodeCopy fee")
k.cpt.gasEip2929AccountCheck(
address, gasFees[k.cpt.fork][GasExtCode])
let codeBytes = k.cpt.getCode(address)
k.cpt.memory.writePaddedResult(codeBytes, memPos, codePos, len)
# -----------
returnDataSizeOp: Vm2OpFn = proc (k: Vm2Ctx) = returnDataSizeOp: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x3d, Get size of output data from the previous call from the ## 0x3d, Get size of output data from the previous call from the
## current environment. ## current environment.
@ -256,6 +309,24 @@ const
"length") "length")
k.cpt.memory.writePaddedResult(k.cpt.returnData, memPos, copyPos, len) k.cpt.memory.writePaddedResult(k.cpt.returnData, memPos, copyPos, len)
# ---------------
extCodeHashOp: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x3f, Returns the keccak256 hash of a contracts code
let address = k.cpt.stack.popAddress()
k.cpt.stack.push:
k.cpt.getCodeHash(address)
extCodeHashEIP2929Op: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x3f, EIP2929: Returns the keccak256 hash of a contracts code
let address = k.cpt.stack.popAddress()
k.cpt.gasEip2929AccountCheck(
address, gasFees[k.cpt.fork][GasExtCodeHash])
k.cpt.stack.push:
k.cpt.getCodeHash(address)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Public, op exec table entries # Public, op exec table entries
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -271,12 +342,19 @@ const
post: vm2OpIgnore)), post: vm2OpIgnore)),
(opCode: Balance, ## 0x31, Balance (opCode: Balance, ## 0x31, Balance
forks: Vm2OpAllForks, forks: Vm2OpAllForks - Vm2OpBerlinAndLater,
info: "Get balance of the given account", info: "Get balance of the given account",
exec: (prep: vm2OpIgnore, exec: (prep: vm2OpIgnore,
run: balanceOp, run: balanceOp,
post: vm2OpIgnore)), post: vm2OpIgnore)),
(opCode: Balance, ## 0x31, Balance for Berlin and later
forks: Vm2OpBerlinAndLater,
info: "EIP2929: Get balance of the given account",
exec: (prep: vm2OpIgnore,
run: balanceEIP2929Op,
post: vm2OpIgnore)),
(opCode: Origin, ## 0x32, Origination address (opCode: Origin, ## 0x32, Origination address
forks: Vm2OpAllForks, forks: Vm2OpAllForks,
info: "Get execution origination address", info: "Get execution origination address",
@ -342,19 +420,33 @@ const
post: vm2OpIgnore)), post: vm2OpIgnore)),
(opCode: ExtCodeSize, ## 0x3b, Account code size (opCode: ExtCodeSize, ## 0x3b, Account code size
forks: Vm2OpAllForks, forks: Vm2OpAllForks - Vm2OpBerlinAndLater,
info: "Get size of an account's code", info: "Get size of an account's code",
exec: (prep: vm2OpIgnore, exec: (prep: vm2OpIgnore,
run: extCodeSizeOp, run: extCodeSizeOp,
post: vm2OpIgnore)), post: vm2OpIgnore)),
(opCode: ExtCodeSize, ## 0x3b, Account code size for Berlin and later
forks: Vm2OpBerlinAndLater,
info: "EIP2929: Get size of an account's code",
exec: (prep: vm2OpIgnore,
run: extCodeSizeEIP2929Op,
post: vm2OpIgnore)),
(opCode: ExtCodeCopy, ## 0x3c, Account code copy to memory. (opCode: ExtCodeCopy, ## 0x3c, Account code copy to memory.
forks: Vm2OpAllForks, forks: Vm2OpAllForks - Vm2OpBerlinAndLater,
info: "Copy an account's code to memory", info: "Copy an account's code to memory",
exec: (prep: vm2OpIgnore, exec: (prep: vm2OpIgnore,
run: extCodeCopyOp, run: extCodeCopyOp,
post: vm2OpIgnore)), post: vm2OpIgnore)),
(opCode: ExtCodeCopy, ## 0x3c, Account Code-copy for Berlin and later
forks: Vm2OpBerlinAndLater,
info: "EIP2929: Copy an account's code to memory",
exec: (prep: vm2OpIgnore,
run: extCodeCopyEIP2929Op,
post: vm2OpIgnore)),
(opCode: ReturnDataSize, ## 0x3d, Previous call output data size (opCode: ReturnDataSize, ## 0x3d, Previous call output data size
forks: Vm2OpAllForks, forks: Vm2OpAllForks,
info: "Get size of output data from the previous call " & info: "Get size of output data from the previous call " &
@ -368,6 +460,20 @@ const
info: "Copy output data from the previous call to memory", info: "Copy output data from the previous call to memory",
exec: (prep: vm2OpIgnore, exec: (prep: vm2OpIgnore,
run: returnDataCopyOp, run: returnDataCopyOp,
post: vm2OpIgnore)),
(opCode: ExtCodeHash, ## 0x3f, Contract hash
forks: Vm2OpAllForks - Vm2OpBerlinAndLater,
info: "Returns the keccak256 hash of a contracts code",
exec: (prep: vm2OpIgnore,
run: extCodeHashOp,
post: vm2OpIgnore)),
(opCode: ExtCodeHash, ## 0x3f, Contract hash for berlin and later
forks: Vm2OpBerlinAndLater,
info: "EIP2929: Returns the keccak256 hash of a contracts code",
exec: (prep: vm2OpIgnore,
run: extCodeHashEIP2929Op,
post: vm2OpIgnore))] post: vm2OpIgnore))]
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -35,11 +35,34 @@ const
when not breakCircularDependency: when not breakCircularDependency:
import import
../../v2types ../../../db/accounts_cache,
../../v2state,
../../v2types,
../gas_meter,
../v2gas_costs,
eth/common
else: else:
const const
emvcStatic = 1 emvcStatic = 1
ColdAccountAccessCost = 2
WarmStorageReadCost = 3
type
GasInt = int
# function stubs from v2state.nim
template mutateStateDB(vmState: BaseVMState, body: untyped) =
block:
var db {.inject.} = vmState.accountDb
body
# 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
# function stubs from gas_meter.nim
proc consumeGas(gasMeter: var GasMeter; amount: int; reason: string) = discard
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Kludge END # Kludge END
@ -63,6 +86,20 @@ proc asText(id, name: string): NimNode {.compileTime.} =
# Public # Public
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
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 checkInStaticContext*(c: Computation) = template checkInStaticContext*(c: Computation) =
## Verify static context in handler function, raise an error otherwise ## Verify static context in handler function, raise an error otherwise
if emvcStatic == c.msg.flags: if emvcStatic == c.msg.flags:

View File

@ -36,7 +36,6 @@ when not breakCircularDependency:
../../stack, ../../stack,
../../v2computation, ../../v2computation,
../../v2memory, ../../v2memory,
../../v2state,
../../v2types, ../../v2types,
../gas_meter, ../gas_meter,
../utils/v2utils_numeric, ../utils/v2utils_numeric,

View File

@ -39,12 +39,15 @@ when not breakCircularDependency:
../gas_meter, ../gas_meter,
../utils/v2utils_numeric, ../utils/v2utils_numeric,
../v2gas_costs, ../v2gas_costs,
eth/common, eth/common
times
else: else:
import macros import macros
const
ColdSloadCost = 42
WarmStorageReadCost = 43
var blindGasCosts: array[Op,int] var blindGasCosts: array[Op,int]
# copied from stack.nim # copied from stack.nim
@ -79,7 +82,10 @@ else:
# function stubs from v2state.nim # function stubs from v2state.nim
proc readOnlyStateDB(x: BaseVMState): ReadOnlyStateDB = x.accountDb proc readOnlyStateDB(x: BaseVMState): ReadOnlyStateDB = x.accountDb
template mutateStateDB(vmState: BaseVMState, body: untyped) = discard template mutateStateDB(vmState: BaseVMState, body: untyped) =
block:
var db {.inject.} = vmState.accountDb
body
# function stubs from gas_meter.nim # function stubs from gas_meter.nim
proc refundGas(gasMeter: var GasMeter; amount: int) = discard proc refundGas(gasMeter: var GasMeter; amount: int) = discard
@ -99,6 +105,11 @@ else:
# function stubs from state_db.nim # function stubs from state_db.nim
proc getCommittedStorage[A,B](x: A; y: B; z: Uint256): Uint256 = 0.u256 proc getCommittedStorage[A,B](x: A; y: B; z: Uint256): Uint256 = 0.u256
# function stubs from accounts_cache.nim:
func inAccessList[A,B](ac: A; address: B; slot: UInt256): bool = false
proc accessList[A,B](ac: var A; address: B; slot: UInt256) = discard
proc setStorage[A,B](ac: var A; address: B, slot, value: UInt256) = discard
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Kludge END # Kludge END
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -195,6 +206,7 @@ const
k.cpt.memory.extend(memPos, 1) k.cpt.memory.extend(memPos, 1)
k.cpt.memory.write(memPos, [value.toByteArrayBE[31]]) k.cpt.memory.write(memPos, [value.toByteArrayBE[31]])
# -------
sloadOp: Vm2OpFn = proc (k: Vm2Ctx) = sloadOp: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x54, Load word from storage. ## 0x54, Load word from storage.
@ -202,6 +214,22 @@ const
k.cpt.stack.push: k.cpt.stack.push:
k.cpt.getStorage(slot) k.cpt.getStorage(slot)
sloadEIP2929Op: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x54, EIP2929: Load word from storage for Berlin and later
let (slot) = k.cpt.stack.popInt(1)
k.cpt.vmState.mutateStateDB:
let gasCost = if not db.inAccessList(k.cpt.msg.contractAddress, slot):
db.accessList(k.cpt.msg.contractAddress, slot)
ColdSloadCost
else:
WarmStorageReadCost
k.cpt.gasMeter.consumeGas(gasCost, reason = "sloadEIP2929")
k.cpt.stack.push:
k.cpt.getStorage(slot)
# -------
sstoreOp: Vm2OpFn = proc (k: Vm2Ctx) = sstoreOp: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x55, Save word to storage. ## 0x55, Save word to storage.
let (slot, newValue) = k.cpt.stack.popInt(2) let (slot, newValue) = k.cpt.stack.popInt(2)
@ -251,6 +279,26 @@ const
sstoreNetGasMeteringImpl(k.cpt, slot, newValue) sstoreNetGasMeteringImpl(k.cpt, slot, newValue)
sstoreEIP2929Op: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x55, EIP2929: sstore for Berlin and later
let (slot, newValue) = k.cpt.stack.popInt(2)
checkInStaticContext(k.cpt)
# Minimum gas required to be present for an SSTORE call, not consumed
const SentryGasEIP2200 = 2300
if k.cpt.gasMeter.gasRemaining <= SentryGasEIP2200:
raise newException(OutOfGas, "Gas not enough to perform EIP2200 SSTORE")
k.cpt.vmState.mutateStateDB:
if not db.inAccessList(k.cpt.msg.contractAddress, slot):
db.accessList(k.cpt.msg.contractAddress, slot)
k.cpt.gasMeter.consumeGas(ColdSloadCost, reason = "sstoreEIP2929")
sstoreNetGasMeteringImpl(k.cpt, slot, newValue)
# -------
jumpOp: Vm2OpFn = proc (k: Vm2Ctx) = jumpOp: Vm2OpFn = proc (k: Vm2Ctx) =
## 0x56, Alter the program counter ## 0x56, Alter the program counter
let (jumpTarget) = k.cpt.stack.popInt(1) let (jumpTarget) = k.cpt.stack.popInt(1)
@ -360,12 +408,19 @@ const
post: vm2OpIgnore)), post: vm2OpIgnore)),
(opCode: Sload, ## 0x54, Load word from storage (opCode: Sload, ## 0x54, Load word from storage
forks: Vm2OpAllForks, forks: Vm2OpAllForks - Vm2OpBerlinAndLater,
info: "Load word from storage", info: "Load word from storage",
exec: (prep: vm2OpIgnore, exec: (prep: vm2OpIgnore,
run: sloadOp, run: sloadOp,
post: vm2OpIgnore)), post: vm2OpIgnore)),
(opCode: Sload, ## 0x54, sload for Berlin and later
forks: Vm2OpBerlinAndLater,
info: "EIP2929: sload for Berlin and later",
exec: (prep: vm2OpIgnore,
run: sloadEIP2929Op,
post: vm2OpIgnore)),
(opCode: Sstore, ## 0x55, Save word (opCode: Sstore, ## 0x55, Save word
forks: Vm2OpAllForks - Vm2OpConstantinopleAndLater, forks: Vm2OpAllForks - Vm2OpConstantinopleAndLater,
info: "Save word to storage", info: "Save word to storage",
@ -381,12 +436,19 @@ const
post: vm2OpIgnore)), post: vm2OpIgnore)),
(opCode: Sstore, ## 0x55, sstore for Istanbul and later (opCode: Sstore, ## 0x55, sstore for Istanbul and later
forks: Vm2OpIstanbulAndLater, forks: Vm2OpIstanbulAndLater - Vm2OpBerlinAndLater,
info: "EIP2200: sstore for Istanbul and later", info: "EIP2200: sstore for Istanbul and later",
exec: (prep: vm2OpIgnore, exec: (prep: vm2OpIgnore,
run: sstoreEIP2200Op, run: sstoreEIP2200Op,
post: vm2OpIgnore)), post: vm2OpIgnore)),
(opCode: Sstore, ## 0x55, sstore for Berlin and later
forks: Vm2OpBerlinAndLater,
info: "EIP2929: sstore for Istanbul and later",
exec: (prep: vm2OpIgnore,
run: sstoreEIP2929Op,
post: vm2OpIgnore)),
(opCode: Jump, ## 0x56, Jump (opCode: Jump, ## 0x56, Jump
forks: Vm2OpIstanbulAndLater, forks: Vm2OpIstanbulAndLater,
info: "Alter the program counter", info: "Alter the program counter",

View File

@ -124,8 +124,8 @@ opHandler sarOp, Op.Sar
opHandler sha3, Op.Sha3 opHandler sha3, Op.Sha3
opHandler address, Op.Address opHandler address, Op.Address
opHandler balance, Op.Balance, FkFrontier opHandler balance, Op.Balance, FkFrontier
opHandler balanceEIP2929, Op.Balance opHandler balanceEIP2929, Op.Balance
opHandler origin, Op.Origin opHandler origin, Op.Origin
opHandler caller, Op.Caller opHandler caller, Op.Caller
@ -145,6 +145,10 @@ opHandler extCodeCopyEIP2929, Op.ExtCodeCopy
opHandler returnDataSize, Op.ReturnDataSize opHandler returnDataSize, Op.ReturnDataSize
opHandler returnDataCopy, Op.ReturnDataCopy opHandler returnDataCopy, Op.ReturnDataCopy
opHandler extCodeHash, Op.ExtCodeHash, FkFrontier
opHandler extCodeHashEIP2929, Op.ExtCodeHash
opHandler blockhash, Op.Blockhash opHandler blockhash, Op.Blockhash
opHandler coinbase, Op.Coinbase opHandler coinbase, Op.Coinbase
opHandler timestamp, Op.Timestamp opHandler timestamp, Op.Timestamp
@ -158,13 +162,13 @@ opHandler mload, Op.Mload
opHandler mstore, Op.Mstore opHandler mstore, Op.Mstore
opHandler mstore8, Op.Mstore8 opHandler mstore8, Op.Mstore8
opHandler sload, Op.Sload, FkFrontier opHandler sload, Op.Sload, FkFrontier
opHandler sloadEIP2929, Op.Sload opHandler sloadEIP2929, Op.Sload
opHandler sstore, Op.Sstore, FkFrontier opHandler sstore, Op.Sstore, FkFrontier
opHandler sstoreEIP1283, Op.Sstore, FkConstantinople opHandler sstoreEIP1283, Op.Sstore, FkConstantinople
opHandler sstoreEIP2200, Op.Sstore, FkIstanbul opHandler sstoreEIP2200, Op.Sstore, FkIstanbul
opHandler sstoreEIP2929, Op.Sstore opHandler sstoreEIP2929, Op.Sstore
opHandler jump, Op.Jump opHandler jump, Op.Jump
opHandler jumpI, Op.JumpI opHandler jumpI, Op.JumpI
@ -545,16 +549,6 @@ op selfDestructEip161, inline = false:
c.selfDestruct(beneficiary) c.selfDestruct(beneficiary)
# Constantinople's new opcodes # Constantinople's new opcodes
#################################
op extCodeHash, inline = true:
let address = c.stack.popAddress()
push: c.getCodeHash(address)
op extCodeHashEIP2929, inline = true:
let address = c.stack.popAddress()
c.gasEip2929AccountCheck(address, gasFees[c.fork][GasExtCodeHash])
push: c.getCodeHash(address)
op selfDestructEIP2929, inline = false: op selfDestructEIP2929, inline = false:
checkInStaticContext(c) checkInStaticContext(c)
@ -577,60 +571,3 @@ op selfDestructEIP2929, inline = false:
c.gasMeter.consumeGas(gasCost, reason = "SELFDESTRUCT EIP161") c.gasMeter.consumeGas(gasCost, reason = "SELFDESTRUCT EIP161")
c.selfDestruct(beneficiary) c.selfDestruct(beneficiary)
# ---------------------------------------------------
op balanceEIP2929x, inline = true:
## 0x31, Get balance of the given account.
let address = c.stack.popAddress()
c.gasEip2929AccountCheck(address, gasFees[c.fork][GasBalance])
push: c.getBalance(address)
op extCodeSizeEIP2929x, inline = true:
## 0x3b, Get size of an account's code
let address = c.stack.popAddress()
c.gasEip2929AccountCheck(address, gasFees[c.fork][GasExtCode])
push: c.getCodeSize(address)
op extCodeCopyEIP2929x, inline = true:
## 0x3c, Copy an account's code to memory.
let address = c.stack.popAddress()
let (memStartPos, codeStartPos, size) = c.stack.popInt(3)
let (memPos, codePos, len) = (memStartPos.cleanMemRef, codeStartPos.cleanMemRef, size.cleanMemRef)
c.gasMeter.consumeGas(
c.gasCosts[ExtCodeCopy].m_handler(c.memory.len, memPos, len),
reason="ExtCodeCopy fee")
c.gasEip2929AccountCheck(address, gasFees[c.fork][GasExtCode])
let codeBytes = c.getCode(address)
c.memory.writePaddedResult(codeBytes, memPos, codePos, len)
op sloadEIP2929x, inline = true, slot:
## 0x54, Load word from storage.
c.vmState.mutateStateDB:
let gasCost = if not db.inAccessList(c.msg.contractAddress, slot):
db.accessList(c.msg.contractAddress, slot)
ColdSloadCost
else:
WarmStorageReadCost
c.gasMeter.consumeGas(gasCost, reason = "sloadEIP2929")
push: c.getStorage(slot)
op sstoreEIP2929x, inline = false, slot, newValue:
checkInStaticContext(c)
const SentryGasEIP2200 = 2300 # Minimum gas required to be present for an SSTORE call, not consumed
if c.gasMeter.gasRemaining <= SentryGasEIP2200:
raise newException(OutOfGas, "Gas not enough to perform EIP2200 SSTORE")
c.vmState.mutateStateDB:
if not db.inAccessList(c.msg.contractAddress, slot):
db.accessList(c.msg.contractAddress, slot)
c.gasMeter.consumeGas(ColdSloadCost, reason = "sstoreEIP2929")
block:
sstoreNetGasMeteringImpl(c, slot, newValue)