2021-04-16 10:53:05 +00:00
|
|
|
# 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
|
|
|
|
## ======================================
|
|
|
|
##
|
|
|
|
|
|
|
|
import
|
2021-04-23 17:43:44 +00:00
|
|
|
../../../constants,
|
2021-04-16 10:53:05 +00:00
|
|
|
../../../errors,
|
2021-04-23 17:43:44 +00:00
|
|
|
../../compu_helper,
|
2021-04-22 16:05:58 +00:00
|
|
|
../../memory,
|
2021-04-23 17:43:44 +00:00
|
|
|
../../stack,
|
|
|
|
../../state,
|
|
|
|
../../types,
|
2021-04-21 17:04:54 +00:00
|
|
|
../forks_list,
|
2021-04-23 17:43:44 +00:00
|
|
|
../gas_costs,
|
|
|
|
../gas_meter,
|
2021-04-21 17:04:54 +00:00
|
|
|
../op_codes,
|
2021-04-22 16:05:58 +00:00
|
|
|
../utils/utils_numeric,
|
2021-04-23 17:43:44 +00:00
|
|
|
./oph_defs,
|
|
|
|
./oph_helpers,
|
2021-04-16 10:53:05 +00:00
|
|
|
chronicles,
|
2021-04-23 17:43:44 +00:00
|
|
|
eth/common,
|
2021-04-21 17:04:54 +00:00
|
|
|
eth/common/eth_types,
|
|
|
|
stint,
|
|
|
|
strformat
|
2021-04-16 10:53:05 +00:00
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
2021-04-23 17:43:44 +00:00
|
|
|
# Private helpers
|
2021-04-16 10:53:05 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
2021-04-23 17:43:44 +00:00
|
|
|
proc execSubCreate(k: var Vm2Ctx; childMsg: Message; salt = 0.u256) =
|
|
|
|
## Create new VM -- helper for `Create`-like operations
|
2021-04-16 10:53:05 +00:00
|
|
|
|
2021-04-23 17:43:44 +00:00
|
|
|
# need to provide explicit <c> and <child> for capturing in chainTo proc()
|
|
|
|
var
|
|
|
|
c = k.cpt
|
|
|
|
child = newComputation(k.cpt.vmState, childMsg, salt)
|
|
|
|
|
|
|
|
k.cpt.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
|
2021-04-16 10:53:05 +00:00
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Private, op handlers implementation
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
const
|
2021-04-20 12:07:01 +00:00
|
|
|
createOp: Vm2OpFn = proc(k: var Vm2Ctx) =
|
2021-04-16 10:53:05 +00:00
|
|
|
## 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
|
|
|
|
|
|
|
|
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")
|
|
|
|
|
2021-04-23 17:43:44 +00:00
|
|
|
k.execSubCreate(
|
|
|
|
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)))
|
2021-04-16 10:53:05 +00:00
|
|
|
|
|
|
|
# ---------------------
|
|
|
|
|
2021-04-20 12:07:01 +00:00
|
|
|
create2Op: Vm2OpFn = proc(k: var Vm2Ctx) =
|
2021-04-16 10:53:05 +00:00
|
|
|
## 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")
|
|
|
|
|
2021-04-23 17:43:44 +00:00
|
|
|
k.execSubCreate(
|
|
|
|
salt = salt,
|
|
|
|
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)))
|
2021-04-16 10:53:05 +00:00
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Public, op exec table entries
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
const
|
|
|
|
vm2OpExecCreate*: seq[Vm2OpExec] = @[
|
|
|
|
|
|
|
|
(opCode: Create, ## 0xf0, Create a new account with associated code
|
|
|
|
forks: Vm2OpAllForks,
|
2021-04-19 09:15:35 +00:00
|
|
|
name: "create",
|
2021-04-16 10:53:05 +00:00
|
|
|
info: "Create a new account with associated code",
|
|
|
|
exec: (prep: vm2OpIgnore,
|
|
|
|
run: createOp,
|
|
|
|
post: vm2OpIgnore)),
|
|
|
|
|
|
|
|
(opCode: Create2, ## 0xf5, Create using keccak256
|
2021-04-19 09:15:35 +00:00
|
|
|
forks: Vm2OpConstantinopleAndLater,
|
|
|
|
name: "create2",
|
2021-04-16 10:53:05 +00:00
|
|
|
info: "Behaves identically to CREATE, except using keccak256",
|
|
|
|
exec: (prep: vm2OpIgnore,
|
|
|
|
run: create2Op,
|
|
|
|
post: vm2OpIgnore))]
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# End
|
|
|
|
# ------------------------------------------------------------------------------
|