mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-12 21:34:33 +00:00
re-integrated/added Create and Create2 handlers
This commit is contained in:
parent
1bb6ef43a1
commit
1bdbfda37f
@ -194,8 +194,7 @@ type
|
|||||||
## alternative account's code, but persisting the
|
## alternative account's code, but persisting the
|
||||||
## current values for sender and value.
|
## current values for sender and value.
|
||||||
Create2 = 0xf5, ## Behaves identically to CREATE, except using
|
Create2 = 0xf5, ## Behaves identically to CREATE, except using
|
||||||
## keccak256( 0xff ++ address ++ salt ++
|
## keccak256
|
||||||
## keccak256(init_code))[12:]
|
|
||||||
|
|
||||||
Nop0xF6, Nop0xF7, Nop0xF8, Nop0xF9, ## ..
|
Nop0xF6, Nop0xF7, Nop0xF8, Nop0xF9, ## ..
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import
|
|||||||
./op_handlers/[oph_defs,
|
./op_handlers/[oph_defs,
|
||||||
oph_arithmetic, oph_hash, oph_envinfo, oph_blockdata,
|
oph_arithmetic, oph_hash, oph_envinfo, oph_blockdata,
|
||||||
oph_memory, oph_push, oph_dup, oph_swap, oph_log,
|
oph_memory, oph_push, oph_dup, oph_swap, oph_log,
|
||||||
oph_sysops]
|
oph_create, oph_sysops]
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Helper
|
# Helper
|
||||||
@ -51,7 +51,7 @@ 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, vm2OpExecCreate, "Create")
|
result.importList(select, vm2OpExecCreate, "Create")
|
||||||
#result.importList(select, vm2OpExecCall, "Call")
|
#result.importList(select, vm2OpExecCall, "Call")
|
||||||
result.importList(select, vm2OpExecSysOp, "SysOp")
|
result.importList(select, vm2OpExecSysOp, "SysOp")
|
||||||
|
|
||||||
|
@ -41,8 +41,6 @@ when not breakCircularDependency:
|
|||||||
else:
|
else:
|
||||||
import macros
|
import macros
|
||||||
|
|
||||||
var 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 =
|
||||||
result = nnkTupleConstr.newNimNode()
|
result = nnkTupleConstr.newNimNode()
|
||||||
@ -50,13 +48,13 @@ 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 popInt(x: var Stack): UInt256 = discard
|
proc popInt(x: var Stack): UInt256 = result
|
||||||
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
|
||||||
|
|
||||||
# function stubs from v2computation.nim (to satisfy compiler logic)
|
# function stubs from v2computation.nim (to satisfy compiler logic)
|
||||||
proc gasCosts(c: Computation): array[Op,int] = blindGasCosts
|
proc gasCosts(c: Computation): array[Op,int] = result
|
||||||
|
|
||||||
# function stubs from v2utils_numeric.nim
|
# function stubs from v2utils_numeric.nim
|
||||||
proc extractSign(v: var UInt256, sign: var bool) = discard
|
proc extractSign(v: var UInt256, sign: var bool) = discard
|
||||||
@ -67,7 +65,7 @@ else:
|
|||||||
proc consumeGas(gasMeter: var GasMeter; amount: int; reason: string) = discard
|
proc consumeGas(gasMeter: var GasMeter; amount: int; reason: string) = discard
|
||||||
|
|
||||||
# stubs from v2gas_costs.nim
|
# stubs from v2gas_costs.nim
|
||||||
proc d_handler(x: int; value: Uint256): int = 0
|
proc d_handler(x: int; value: Uint256): int = result
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Kludge END
|
# Kludge END
|
||||||
|
255
nimbus/vm2/interpreter/op_handlers/oph_create.nim
Normal file
255
nimbus/vm2/interpreter/op_handlers/oph_create.nim
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
# Nimbus
|
||||||
|
# Copyright (c) 2018 Status Research & Development GmbH
|
||||||
|
# Licensed under either of
|
||||||
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
||||||
|
# http://opensource.org/licenses/MIT)
|
||||||
|
# at your option. This file may not be copied, modified, or distributed except
|
||||||
|
# according to those terms.
|
||||||
|
|
||||||
|
## EVM Opcode Handlers: Create Operations
|
||||||
|
## ======================================
|
||||||
|
##
|
||||||
|
|
||||||
|
const
|
||||||
|
kludge {.intdefine.}: int = 0
|
||||||
|
breakCircularDependency {.used.} = kludge > 0
|
||||||
|
|
||||||
|
import
|
||||||
|
../../../errors,
|
||||||
|
./oph_defs,
|
||||||
|
./oph_helpers,
|
||||||
|
chronicles,
|
||||||
|
strformat,
|
||||||
|
stint
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Kludge BEGIN
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
when not breakCircularDependency:
|
||||||
|
import
|
||||||
|
../../../constants,
|
||||||
|
../../stack,
|
||||||
|
../../v2computation,
|
||||||
|
../../v2memory,
|
||||||
|
../../v2state,
|
||||||
|
../../v2types,
|
||||||
|
../gas_meter,
|
||||||
|
../utils/v2utils_numeric,
|
||||||
|
../v2gas_costs,
|
||||||
|
eth/common
|
||||||
|
|
||||||
|
else:
|
||||||
|
import macros
|
||||||
|
|
||||||
|
type
|
||||||
|
GasResult = tuple[gasCost, gasRefund: GasInt]
|
||||||
|
const
|
||||||
|
evmcCreate = 42
|
||||||
|
evmcCreate2 = 43
|
||||||
|
MaxCallDepth = 45
|
||||||
|
|
||||||
|
# function stubs from stack.nim (to satisfy compiler logic)
|
||||||
|
proc top[T](x: Stack, value: T) = discard
|
||||||
|
proc peekInt(x: Stack): UInt256 = result
|
||||||
|
proc popInt(x: var Stack): UInt256 = result
|
||||||
|
|
||||||
|
# function stubs from v2computation.nim (to satisfy compiler logic)
|
||||||
|
proc gasCosts(c: Computation): array[Op,int] = result
|
||||||
|
proc getBalance[T](c: Computation, address: T): Uint256 = result
|
||||||
|
proc newComputation[A,B](v:A, m:B, salt = 0.u256): Computation = new result
|
||||||
|
func shouldBurnGas(c: Computation): bool = result
|
||||||
|
proc isSuccess(c: Computation): bool = result
|
||||||
|
proc merge(c, child: Computation) = discard
|
||||||
|
template chainTo(c, d: Computation, e: untyped) =
|
||||||
|
c.child = d; c.continuation = proc() = e
|
||||||
|
|
||||||
|
# function stubs from v2utils_numeric.nim
|
||||||
|
func safeInt(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 gas_meter.nim
|
||||||
|
proc consumeGas(gasMeter: var GasMeter; amount: int; reason: string) = discard
|
||||||
|
proc returnGas(gasMeter: var GasMeter; amount: GasInt) = discard
|
||||||
|
|
||||||
|
# stubs from v2gas_costs.nim
|
||||||
|
type GasParams = object
|
||||||
|
case kind*: Op
|
||||||
|
of Create:
|
||||||
|
cr_currentMemSize, cr_memOffset, cr_memLength: int64
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
proc c_handler(x: int; y: Uint256, z: GasParams): GasResult = result
|
||||||
|
proc m_handler(x: int; curMemSize, memOffset, memLen: int64): int = result
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Kludge END
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Private, op handlers implementation
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const
|
||||||
|
createOp: Vm2OpFn = proc(k: Vm2Ctx) =
|
||||||
|
## 0xf0, Create a new account with associated code
|
||||||
|
checkInStaticContext(k.cpt)
|
||||||
|
|
||||||
|
let
|
||||||
|
endowment = k.cpt.stack.popInt()
|
||||||
|
memPos = k.cpt.stack.popInt().safeInt
|
||||||
|
memLen = k.cpt.stack.peekInt().safeInt
|
||||||
|
salt = 0.u256
|
||||||
|
|
||||||
|
k.cpt.stack.top(0)
|
||||||
|
|
||||||
|
let gasParams = GasParams(
|
||||||
|
kind: Create,
|
||||||
|
cr_currentMemSize: k.cpt.memory.len,
|
||||||
|
cr_memOffset: memPos,
|
||||||
|
cr_memLength: memLen)
|
||||||
|
|
||||||
|
var gasCost = k.cpt.gasCosts[Create].c_handler(1.u256, gasParams).gasCost
|
||||||
|
k.cpt.gasMeter.consumeGas(
|
||||||
|
gasCost, reason = &"CREATE: GasCreate + {memLen} * memory expansion")
|
||||||
|
k.cpt.memory.extend(memPos, memLen)
|
||||||
|
k.cpt.returnData.setLen(0)
|
||||||
|
|
||||||
|
if k.cpt.msg.depth >= MaxCallDepth:
|
||||||
|
debug "Computation Failure",
|
||||||
|
reason = "Stack too deep",
|
||||||
|
maxDepth = MaxCallDepth,
|
||||||
|
depth = k.cpt.msg.depth
|
||||||
|
return
|
||||||
|
|
||||||
|
if endowment != 0:
|
||||||
|
let senderBalance = k.cpt.getBalance(k.cpt.msg.contractAddress)
|
||||||
|
if senderBalance < endowment:
|
||||||
|
debug "Computation Failure",
|
||||||
|
reason = "Insufficient funds available to transfer",
|
||||||
|
required = endowment,
|
||||||
|
balance = senderBalance
|
||||||
|
return
|
||||||
|
|
||||||
|
var createMsgGas = k.cpt.gasMeter.gasRemaining
|
||||||
|
if k.cpt.fork >= FkTangerine:
|
||||||
|
createMsgGas -= createMsgGas div 64
|
||||||
|
k.cpt.gasMeter.consumeGas(createMsgGas, reason = "CREATE")
|
||||||
|
|
||||||
|
let childMsg = Message(
|
||||||
|
kind: evmcCreate,
|
||||||
|
depth: k.cpt.msg.depth + 1,
|
||||||
|
gas: createMsgGas,
|
||||||
|
sender: k.cpt.msg.contractAddress,
|
||||||
|
value: endowment,
|
||||||
|
data: k.cpt.memory.read(memPos, memLen))
|
||||||
|
|
||||||
|
var child = newComputation(k.cpt.vmState, childMsg, salt)
|
||||||
|
k.cpt.chainTo(child):
|
||||||
|
if not child.shouldBurnGas:
|
||||||
|
k.cpt.gasMeter.returnGas(child.gasMeter.gasRemaining)
|
||||||
|
|
||||||
|
if child.isSuccess:
|
||||||
|
k.cpt.merge(child)
|
||||||
|
k.cpt.stack.top child.msg.contractAddress
|
||||||
|
else:
|
||||||
|
k.cpt.returnData = child.output
|
||||||
|
|
||||||
|
# ---------------------
|
||||||
|
|
||||||
|
create2Op: Vm2OpFn = proc(k: Vm2Ctx) =
|
||||||
|
## 0xf5, Behaves identically to CREATE, except using keccak256
|
||||||
|
checkInStaticContext(k.cpt)
|
||||||
|
|
||||||
|
let
|
||||||
|
endowment = k.cpt.stack.popInt()
|
||||||
|
memPos = k.cpt.stack.popInt().safeInt
|
||||||
|
memLen = k.cpt.stack.popInt().safeInt
|
||||||
|
salt = k.cpt.stack.peekInt()
|
||||||
|
|
||||||
|
k.cpt.stack.top(0)
|
||||||
|
|
||||||
|
let gasParams = GasParams(
|
||||||
|
kind: Create,
|
||||||
|
cr_currentMemSize: k.cpt.memory.len,
|
||||||
|
cr_memOffset: memPos,
|
||||||
|
cr_memLength: memLen)
|
||||||
|
|
||||||
|
var gasCost = k.cpt.gasCosts[Create].c_handler(1.u256, gasParams).gasCost
|
||||||
|
gasCost = gasCost + k.cpt.gasCosts[Create2].m_handler(0, 0, memLen)
|
||||||
|
|
||||||
|
k.cpt.gasMeter.consumeGas(
|
||||||
|
gasCost, reason = &"CREATE: GasCreate + {memLen} * memory expansion")
|
||||||
|
k.cpt.memory.extend(memPos, memLen)
|
||||||
|
k.cpt.returnData.setLen(0)
|
||||||
|
|
||||||
|
if k.cpt.msg.depth >= MaxCallDepth:
|
||||||
|
debug "Computation Failure",
|
||||||
|
reason = "Stack too deep",
|
||||||
|
maxDepth = MaxCallDepth,
|
||||||
|
depth = k.cpt.msg.depth
|
||||||
|
return
|
||||||
|
|
||||||
|
if endowment != 0:
|
||||||
|
let senderBalance = k.cpt.getBalance(k.cpt.msg.contractAddress)
|
||||||
|
if senderBalance < endowment:
|
||||||
|
debug "Computation Failure",
|
||||||
|
reason = "Insufficient funds available to transfer",
|
||||||
|
required = endowment,
|
||||||
|
balance = senderBalance
|
||||||
|
return
|
||||||
|
|
||||||
|
var createMsgGas = k.cpt.gasMeter.gasRemaining
|
||||||
|
if k.cpt.fork >= FkTangerine:
|
||||||
|
createMsgGas -= createMsgGas div 64
|
||||||
|
k.cpt.gasMeter.consumeGas(createMsgGas, reason = "CREATE")
|
||||||
|
|
||||||
|
let childMsg = Message(
|
||||||
|
kind: evmcCreate2,
|
||||||
|
depth: k.cpt.msg.depth + 1,
|
||||||
|
gas: createMsgGas,
|
||||||
|
sender: k.cpt.msg.contractAddress,
|
||||||
|
value: endowment,
|
||||||
|
data: k.cpt.memory.read(memPos, memLen))
|
||||||
|
|
||||||
|
var child = newComputation(k.cpt.vmState, childMsg, salt)
|
||||||
|
k.cpt.chainTo(child):
|
||||||
|
if not child.shouldBurnGas:
|
||||||
|
k.cpt.gasMeter.returnGas(child.gasMeter.gasRemaining)
|
||||||
|
|
||||||
|
if child.isSuccess:
|
||||||
|
k.cpt.merge(child)
|
||||||
|
k.cpt.stack.top child.msg.contractAddress
|
||||||
|
else:
|
||||||
|
k.cpt.returnData = child.output
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Public, op exec table entries
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const
|
||||||
|
vm2OpExecCreate*: seq[Vm2OpExec] = @[
|
||||||
|
|
||||||
|
(opCode: Create, ## 0xf0, Create a new account with associated code
|
||||||
|
forks: Vm2OpAllForks,
|
||||||
|
info: "Create a new account with associated code",
|
||||||
|
exec: (prep: vm2OpIgnore,
|
||||||
|
run: createOp,
|
||||||
|
post: vm2OpIgnore)),
|
||||||
|
|
||||||
|
(opCode: Create2, ## 0xf5, Create using keccak256
|
||||||
|
forks: Vm2OpAllForks,
|
||||||
|
info: "Behaves identically to CREATE, except using keccak256",
|
||||||
|
exec: (prep: vm2OpIgnore,
|
||||||
|
run: create2Op,
|
||||||
|
post: vm2OpIgnore))]
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# End
|
||||||
|
# ------------------------------------------------------------------------------
|
@ -37,6 +37,8 @@ else:
|
|||||||
{.fatal: "Flag \"vm2_enabled\" must be unset "&
|
{.fatal: "Flag \"vm2_enabled\" must be unset "&
|
||||||
"while circular dependency breaker kludge is activated".}
|
"while circular dependency breaker kludge is activated".}
|
||||||
type
|
type
|
||||||
|
GasInt* = int
|
||||||
|
|
||||||
ReadOnlyStateDB* =
|
ReadOnlyStateDB* =
|
||||||
seq[byte]
|
seq[byte]
|
||||||
|
|
||||||
@ -51,8 +53,11 @@ else:
|
|||||||
accountDb*: ReadOnlyStateDB
|
accountDb*: ReadOnlyStateDB
|
||||||
|
|
||||||
Message* = ref object
|
Message* = ref object
|
||||||
|
kind*: int
|
||||||
|
depth*: int
|
||||||
|
gas*: GasInt
|
||||||
contractAddress*: EthAddress
|
contractAddress*: EthAddress
|
||||||
sender*: UInt256
|
sender*: EthAddress
|
||||||
value*: UInt256
|
value*: UInt256
|
||||||
data*: seq[byte]
|
data*: seq[byte]
|
||||||
flags*: int
|
flags*: int
|
||||||
@ -68,6 +73,8 @@ else:
|
|||||||
code*: CodeStream
|
code*: CodeStream
|
||||||
returnData*: seq[byte]
|
returnData*: seq[byte]
|
||||||
fork*: Fork
|
fork*: Fork
|
||||||
|
parent*, child*: Computation
|
||||||
|
continuation*: proc() {.gcsafe.}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Kludge END
|
# Kludge END
|
||||||
|
@ -47,8 +47,6 @@ else:
|
|||||||
emvcStatic = 1
|
emvcStatic = 1
|
||||||
ColdAccountAccessCost = 2
|
ColdAccountAccessCost = 2
|
||||||
WarmStorageReadCost = 3
|
WarmStorageReadCost = 3
|
||||||
type
|
|
||||||
GasInt = int
|
|
||||||
|
|
||||||
# function stubs from v2state.nim
|
# function stubs from v2state.nim
|
||||||
template mutateStateDB(vmState: BaseVMState, body: untyped) =
|
template mutateStateDB(vmState: BaseVMState, body: untyped) =
|
||||||
|
@ -43,14 +43,9 @@ else:
|
|||||||
import macros
|
import macros
|
||||||
|
|
||||||
type
|
type
|
||||||
GasInt = int
|
|
||||||
GasResult = tuple[gasCost, gasRefund: GasInt]
|
GasResult = tuple[gasCost, gasRefund: GasInt]
|
||||||
const
|
const
|
||||||
ColdAccountAccessCost = 42
|
ColdAccountAccessCost = 42
|
||||||
var
|
|
||||||
blindGasCosts: array[Op,int]
|
|
||||||
blindAddress: EthAddress
|
|
||||||
blindGasResult: GasResult
|
|
||||||
|
|
||||||
# copied from stack.nim
|
# copied from stack.nim
|
||||||
macro genTupleType(len: static[int], elemType: untyped): untyped =
|
macro genTupleType(len: static[int], elemType: untyped): untyped =
|
||||||
@ -58,23 +53,23 @@ else:
|
|||||||
for i in 0 ..< len: result.add(elemType)
|
for i in 0 ..< len: result.add(elemType)
|
||||||
|
|
||||||
# function stubs from stack.nim (to satisfy compiler logic)
|
# function stubs from stack.nim (to satisfy compiler logic)
|
||||||
proc popAddress(x: var Stack): EthAddress = blindAddress
|
proc popAddress(x: var Stack): EthAddress = result
|
||||||
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
|
||||||
|
|
||||||
# function stubs from v2computation.nim (to satisfy compiler logic)
|
# function stubs from v2computation.nim (to satisfy compiler logic)
|
||||||
proc gasCosts(c: Computation): array[Op,int] = blindGasCosts
|
proc gasCosts(c: Computation): array[Op,int] = result
|
||||||
proc setError(c: Computation, msg: string, burnsGas = false) = discard
|
proc setError(c: Computation, msg: string, burnsGas = false) = discard
|
||||||
proc selfDestruct(c: Computation, address: EthAddress) = discard
|
proc selfDestruct(c: Computation, address: EthAddress) = discard
|
||||||
proc accountExists(c: Computation, address: EthAddress): bool = false
|
proc accountExists(c: Computation, address: EthAddress): bool = result
|
||||||
proc getBalance[T](c: Computation, address: T): Uint256 = 0.u256
|
proc getBalance[T](c: Computation, address: T): Uint256 = result
|
||||||
|
|
||||||
# function stubs from v2utils_numeric.nim
|
# function stubs from v2utils_numeric.nim
|
||||||
func cleanMemRef(x: UInt256): int = 0
|
func cleanMemRef(x: UInt256): int = result
|
||||||
|
|
||||||
# function stubs from v2memory.nim
|
# function stubs from v2memory.nim
|
||||||
proc len(mem: Memory): int = 0
|
proc len(mem: Memory): int = result
|
||||||
proc extend(mem: var Memory; startPos: Natural; size: Natural) = discard
|
proc extend(mem: var Memory; startPos: Natural; size: Natural) = discard
|
||||||
proc read(mem: var Memory, startPos: Natural, size: Natural): seq[byte] = @[]
|
proc read(mem: var Memory, startPos: Natural, size: Natural): seq[byte] = @[]
|
||||||
|
|
||||||
@ -94,11 +89,11 @@ else:
|
|||||||
sd_condition: bool
|
sd_condition: bool
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
proc c_handler(x: int; y: Uint256, z: GasParams): GasResult = blindGasResult
|
proc c_handler(x: int; y: Uint256, z: GasParams): GasResult = result
|
||||||
proc m_handler(x: int; curMemSize, memOffset, memLen: int64): int = 0
|
proc m_handler(x: int; curMemSize, memOffset, memLen: int64): int = result
|
||||||
|
|
||||||
# function stubs from accounts_cache.nim:
|
# function stubs from accounts_cache.nim:
|
||||||
func inAccessList[A,B](ac: A; address: B): bool = false
|
func inAccessList[A,B](ac: A; address: B): bool = result
|
||||||
proc accessList[A,B](ac: var A; address: B) = discard
|
proc accessList[A,B](ac: var A; address: B) = discard
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -202,6 +202,8 @@ 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 create, Op.Create
|
||||||
|
opHandler create2, Op.Create2
|
||||||
opHandler returnOp, Op.Return
|
opHandler returnOp, Op.Return
|
||||||
opHandler revert, Op.Revert
|
opHandler revert, Op.Revert
|
||||||
opHandler invalidOp, Op.Invalid
|
opHandler invalidOp, Op.Invalid
|
||||||
@ -213,76 +215,6 @@ opHandler selfDestructEIP2929, Op.SelfDestruct
|
|||||||
|
|
||||||
# ##########################################
|
# ##########################################
|
||||||
# f0s: System operations.
|
# f0s: System operations.
|
||||||
template genCreate(callName: untyped, opCode: Op): untyped =
|
|
||||||
op callName, inline = false:
|
|
||||||
checkInStaticContext(c)
|
|
||||||
let
|
|
||||||
endowment = c.stack.popInt()
|
|
||||||
memPos = c.stack.popInt().safeInt
|
|
||||||
|
|
||||||
when opCode == Create:
|
|
||||||
const callKind = evmcCreate
|
|
||||||
let memLen {.inject.} = c.stack.peekInt().safeInt
|
|
||||||
let salt = 0.u256
|
|
||||||
else:
|
|
||||||
const callKind = evmcCreate2
|
|
||||||
let memLen {.inject.} = c.stack.popInt().safeInt
|
|
||||||
let salt = c.stack.peekInt()
|
|
||||||
|
|
||||||
c.stack.top(0)
|
|
||||||
|
|
||||||
let gasParams = GasParams(kind: Create,
|
|
||||||
cr_currentMemSize: c.memory.len,
|
|
||||||
cr_memOffset: memPos,
|
|
||||||
cr_memLength: memLen
|
|
||||||
)
|
|
||||||
var gasCost = c.gasCosts[Create].c_handler(1.u256, gasParams).gasCost
|
|
||||||
when opCode == Create2:
|
|
||||||
gasCost = gasCost + c.gasCosts[Create2].m_handler(0, 0, memLen)
|
|
||||||
|
|
||||||
let reason = &"CREATE: GasCreate + {memLen} * memory expansion"
|
|
||||||
c.gasMeter.consumeGas(gasCost, reason = reason)
|
|
||||||
c.memory.extend(memPos, memLen)
|
|
||||||
c.returnData.setLen(0)
|
|
||||||
|
|
||||||
if c.msg.depth >= MaxCallDepth:
|
|
||||||
debug "Computation Failure", reason = "Stack too deep", maxDepth = MaxCallDepth, depth = c.msg.depth
|
|
||||||
return
|
|
||||||
|
|
||||||
if endowment != 0:
|
|
||||||
let senderBalance = c.getBalance(c.msg.contractAddress)
|
|
||||||
if senderBalance < endowment:
|
|
||||||
debug "Computation Failure", reason = "Insufficient funds available to transfer", required = endowment, balance = senderBalance
|
|
||||||
return
|
|
||||||
|
|
||||||
var createMsgGas = c.gasMeter.gasRemaining
|
|
||||||
if c.fork >= FkTangerine:
|
|
||||||
createMsgGas -= createMsgGas div 64
|
|
||||||
c.gasMeter.consumeGas(createMsgGas, reason="CREATE")
|
|
||||||
|
|
||||||
block:
|
|
||||||
let childMsg = Message(
|
|
||||||
kind: callKind,
|
|
||||||
depth: c.msg.depth + 1,
|
|
||||||
gas: createMsgGas,
|
|
||||||
sender: c.msg.contractAddress,
|
|
||||||
value: endowment,
|
|
||||||
data: c.memory.read(memPos, memLen)
|
|
||||||
)
|
|
||||||
|
|
||||||
var child = newComputation(c.vmState, childMsg, salt)
|
|
||||||
c.chainTo(child):
|
|
||||||
if not child.shouldBurnGas:
|
|
||||||
c.gasMeter.returnGas(child.gasMeter.gasRemaining)
|
|
||||||
|
|
||||||
if child.isSuccess:
|
|
||||||
c.merge(child)
|
|
||||||
c.stack.top child.msg.contractAddress
|
|
||||||
else:
|
|
||||||
c.returnData = child.output
|
|
||||||
|
|
||||||
genCreate(create, Create)
|
|
||||||
genCreate(create2, Create2)
|
|
||||||
|
|
||||||
proc callParams(c: Computation): (UInt256, UInt256, EthAddress, EthAddress, CallKind, int, int, int, int, MsgFlags) =
|
proc callParams(c: Computation): (UInt256, UInt256, EthAddress, EthAddress, CallKind, int, int, int, int, MsgFlags) =
|
||||||
let gas = c.stack.popInt()
|
let gas = c.stack.popInt()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user