clean up code for call handlers
This commit is contained in:
parent
4ac32d360b
commit
4e2af7937b
|
@ -118,83 +118,107 @@ else:
|
||||||
# Private
|
# Private
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc callParams(c: Computation): (UInt256, UInt256, EthAddress,
|
type
|
||||||
EthAddress, int, int, int,
|
LocalParams = tuple
|
||||||
int, MsgFlags) =
|
gas: UInt256
|
||||||
let gas = c.stack.popInt()
|
value: UInt256
|
||||||
let destination = c.stack.popAddress()
|
destination: EthAddress
|
||||||
let value = c.stack.popInt()
|
sender: EthAddress
|
||||||
|
memInPos: int
|
||||||
|
memInLen: int
|
||||||
|
memOutPos: int
|
||||||
|
memOutLen: int
|
||||||
|
flags: MsgFlags
|
||||||
|
memOffset: int
|
||||||
|
memLength: int
|
||||||
|
contractAddress: EthAddress
|
||||||
|
|
||||||
result = (gas,
|
|
||||||
value,
|
|
||||||
destination,
|
|
||||||
c.msg.contractAddress, # sender
|
|
||||||
c.stack.popInt().cleanMemRef,
|
|
||||||
c.stack.popInt().cleanMemRef,
|
|
||||||
c.stack.popInt().cleanMemRef,
|
|
||||||
c.stack.popInt().cleanMemRef,
|
|
||||||
c.msg.flags)
|
|
||||||
|
|
||||||
|
proc updateStackAndParams(q: var LocalParams; c: Computation) =
|
||||||
c.stack.push(0)
|
c.stack.push(0)
|
||||||
|
|
||||||
|
let
|
||||||
|
outLen = calcMemSize(q.memOutPos, q.memOutLen)
|
||||||
|
inLen = calcMemSize(q.memInPos, q.memInLen)
|
||||||
|
|
||||||
proc callCodeParams(c: Computation): (UInt256, UInt256, EthAddress,
|
# get the bigger one
|
||||||
EthAddress, int, int, int,
|
if outLen < inLen:
|
||||||
int, MsgFlags) =
|
q.memOffset = q.memInPos
|
||||||
let gas = c.stack.popInt()
|
q.memLength = q.memInLen
|
||||||
let destination = c.stack.popAddress()
|
else:
|
||||||
let value = c.stack.popInt()
|
q.memOffset = q.memOutPos
|
||||||
|
q.memLength = q.memOutLen
|
||||||
|
|
||||||
result = (gas,
|
# EIP2929: This came before old gas calculator
|
||||||
value,
|
# because it will affect `c.gasMeter.gasRemaining`
|
||||||
destination,
|
# and further `childGasLimit`
|
||||||
c.msg.contractAddress, # sender
|
if FkBerlin <= c.fork:
|
||||||
c.stack.popInt().cleanMemRef,
|
c.vmState.mutateStateDB:
|
||||||
c.stack.popInt().cleanMemRef,
|
if not db.inAccessList(q.destination):
|
||||||
c.stack.popInt().cleanMemRef,
|
db.accessList(q.destination)
|
||||||
c.stack.popInt().cleanMemRef,
|
|
||||||
c.msg.flags)
|
|
||||||
|
|
||||||
c.stack.push(0)
|
# The WarmStorageReadCostEIP2929 (100) is already deducted in
|
||||||
|
# the form of a constant `gasCall`
|
||||||
|
c.gasMeter.consumeGas(
|
||||||
|
ColdAccountAccessCost - WarmStorageReadCost,
|
||||||
|
reason = "EIP2929 gasCall")
|
||||||
|
|
||||||
|
|
||||||
|
proc callParams(c: Computation): LocalParams =
|
||||||
|
## Helper for callOp()
|
||||||
|
result.gas = c.stack.popInt()
|
||||||
|
result.destination = c.stack.popAddress()
|
||||||
|
result.value = c.stack.popInt()
|
||||||
|
result.memInPos = c.stack.popInt().cleanMemRef
|
||||||
|
result.memInLen = c.stack.popInt().cleanMemRef
|
||||||
|
result.memOutPos = c.stack.popInt().cleanMemRef
|
||||||
|
result.memOutLen = c.stack.popInt().cleanMemRef
|
||||||
|
|
||||||
proc delegateCallParams(c: Computation): (UInt256, UInt256, EthAddress,
|
result.sender = c.msg.contractAddress
|
||||||
EthAddress, int, int, int,
|
result.flags = c.msg.flags
|
||||||
int, MsgFlags) =
|
result.contractAddress = result.destination
|
||||||
let gas = c.stack.popInt()
|
|
||||||
let destination = c.stack.popAddress()
|
|
||||||
|
|
||||||
result = (gas,
|
result.updateStackAndParams(c)
|
||||||
c.msg.value, # value
|
|
||||||
destination,
|
|
||||||
c.msg.sender, # sender
|
|
||||||
c.stack.popInt().cleanMemRef,
|
|
||||||
c.stack.popInt().cleanMemRef,
|
|
||||||
c.stack.popInt().cleanMemRef,
|
|
||||||
c.stack.popInt().cleanMemRef,
|
|
||||||
c.msg.flags)
|
|
||||||
|
|
||||||
c.stack.push(0)
|
|
||||||
|
|
||||||
|
|
||||||
proc staticCallParams(c: Computation): (UInt256, UInt256, EthAddress,
|
proc callCodeParams(c: Computation): LocalParams =
|
||||||
EthAddress, int, int, int,
|
## Helper for callCodeOp()
|
||||||
int, MsgFlags) =
|
result = c.callParams
|
||||||
let gas = c.stack.popInt()
|
result.contractAddress = c.msg.contractAddress
|
||||||
let destination = c.stack.popAddress()
|
|
||||||
|
|
||||||
result = (gas,
|
|
||||||
0.u256, # value
|
|
||||||
destination,
|
|
||||||
c.msg.contractAddress, # sender
|
|
||||||
c.stack.popInt().cleanMemRef,
|
|
||||||
c.stack.popInt().cleanMemRef,
|
|
||||||
c.stack.popInt().cleanMemRef,
|
|
||||||
c.stack.popInt().cleanMemRef,
|
|
||||||
emvcStatic) # is_static
|
|
||||||
|
|
||||||
c.stack.push(0)
|
proc delegateCallParams(c: Computation): LocalParams =
|
||||||
|
## Helper for delegateCall()
|
||||||
|
result.gas = c.stack.popInt()
|
||||||
|
result.destination = c.stack.popAddress()
|
||||||
|
result.memInPos = c.stack.popInt().cleanMemRef
|
||||||
|
result.memInLen = c.stack.popInt().cleanMemRef
|
||||||
|
result.memOutPos = c.stack.popInt().cleanMemRef
|
||||||
|
result.memOutLen = c.stack.popInt().cleanMemRef
|
||||||
|
|
||||||
|
result.value = c.msg.value
|
||||||
|
result.sender = c.msg.sender
|
||||||
|
result.flags = c.msg.flags
|
||||||
|
result.contractAddress = c.msg.contractAddress
|
||||||
|
|
||||||
|
result.updateStackAndParams(c)
|
||||||
|
|
||||||
|
|
||||||
|
proc staticCallParams(c: Computation): LocalParams =
|
||||||
|
## Helper for staticCall()
|
||||||
|
result.gas = c.stack.popInt()
|
||||||
|
result.destination = c.stack.popAddress()
|
||||||
|
result.memInPos = c.stack.popInt().cleanMemRef
|
||||||
|
result.memInLen = c.stack.popInt().cleanMemRef
|
||||||
|
result.memOutPos = c.stack.popInt().cleanMemRef
|
||||||
|
result.memOutLen = c.stack.popInt().cleanMemRef
|
||||||
|
|
||||||
|
result.value = 0.u256
|
||||||
|
result.sender = c.msg.contractAddress
|
||||||
|
result.flags = emvcStatic
|
||||||
|
result.contractAddress = result.destination
|
||||||
|
|
||||||
|
result.updateStackAndParams(c)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Private, op handlers implementation
|
# Private, op handlers implementation
|
||||||
|
@ -203,46 +227,24 @@ proc staticCallParams(c: Computation): (UInt256, UInt256, EthAddress,
|
||||||
const
|
const
|
||||||
callOp: Vm2OpFn = proc(k: Vm2Ctx) =
|
callOp: Vm2OpFn = proc(k: Vm2Ctx) =
|
||||||
## 0xf1, Message-Call into an account
|
## 0xf1, Message-Call into an account
|
||||||
|
|
||||||
if emvcStatic == k.cpt.msg.flags and k.cpt.stack[^3, UInt256] > 0.u256:
|
if emvcStatic == k.cpt.msg.flags and k.cpt.stack[^3, UInt256] > 0.u256:
|
||||||
raise newException(
|
raise newException(
|
||||||
StaticContextError,
|
StaticContextError,
|
||||||
"Cannot modify state while inside of a STATICCALL context")
|
"Cannot modify state while inside of a STATICCALL context")
|
||||||
|
let
|
||||||
let (gas, value, destination, sender, memInPos, memInLen, memOutPos,
|
p = k.cpt.callParams
|
||||||
memOutLen, flags) = callParams(k.cpt)
|
|
||||||
|
|
||||||
let (memOffset, memLength) =
|
|
||||||
if calcMemSize(memInPos, memInLen) > calcMemSize(memOutPos, memOutLen):
|
|
||||||
(memInPos, memInLen)
|
|
||||||
else:
|
|
||||||
(memOutPos, memOutLen)
|
|
||||||
|
|
||||||
# EIP2929
|
|
||||||
# This came before old gas calculator
|
|
||||||
# because it will affect `k.cpt.gasMeter.gasRemaining`
|
|
||||||
# and further `childGasLimit`
|
|
||||||
if k.cpt.fork >= FkBerlin:
|
|
||||||
k.cpt.vmState.mutateStateDB:
|
|
||||||
if not db.inAccessList(destination):
|
|
||||||
db.accessList(destination)
|
|
||||||
# The WarmStorageReadCostEIP2929 (100) is already deducted in
|
|
||||||
# the form of a constant `gasCall`
|
|
||||||
k.cpt.gasMeter.consumeGas(
|
|
||||||
ColdAccountAccessCost - WarmStorageReadCost,
|
|
||||||
reason = "EIP2929 gasCall")
|
|
||||||
|
|
||||||
let contractAddress = destination
|
|
||||||
|
|
||||||
var (gasCost, childGasLimit) = k.cpt.gasCosts[Call].c_handler(
|
var (gasCost, childGasLimit) = k.cpt.gasCosts[Call].c_handler(
|
||||||
value,
|
p.value,
|
||||||
GasParams(
|
GasParams(
|
||||||
kind: Call,
|
kind: Call,
|
||||||
c_isNewAccount: not k.cpt.accountExists(contractAddress),
|
c_isNewAccount: not k.cpt.accountExists(p.contractAddress),
|
||||||
c_gasBalance: k.cpt.gasMeter.gasRemaining,
|
c_gasBalance: k.cpt.gasMeter.gasRemaining,
|
||||||
c_contractGas: gas,
|
c_contractGas: p.gas,
|
||||||
c_currentMemSize: k.cpt.memory.len,
|
c_currentMemSize: k.cpt.memory.len,
|
||||||
c_memOffset: memOffset,
|
c_memOffset: p.memOffset,
|
||||||
c_memLength: memLength))
|
c_memLength: p.memLength))
|
||||||
|
|
||||||
# EIP 2046: temporary disabled
|
# EIP 2046: temporary disabled
|
||||||
# reduce gas fee for precompiles
|
# reduce gas fee for precompiles
|
||||||
|
@ -264,11 +266,11 @@ const
|
||||||
raise newException(
|
raise newException(
|
||||||
OutOfGas, "Gas not enough to perform calculation (call)")
|
OutOfGas, "Gas not enough to perform calculation (call)")
|
||||||
|
|
||||||
k.cpt.memory.extend(memInPos, memInLen)
|
k.cpt.memory.extend(p.memInPos, p.memInLen)
|
||||||
k.cpt.memory.extend(memOutPos, memOutLen)
|
k.cpt.memory.extend(p.memOutPos, p.memOutLen)
|
||||||
|
|
||||||
let senderBalance = k.cpt.getBalance(sender)
|
let senderBalance = k.cpt.getBalance(p.sender)
|
||||||
if senderBalance < value:
|
if senderBalance < p.value:
|
||||||
debug "Insufficient funds",
|
debug "Insufficient funds",
|
||||||
available = senderBalance,
|
available = senderBalance,
|
||||||
needed = k.cpt.msg.value
|
needed = k.cpt.msg.value
|
||||||
|
@ -279,12 +281,12 @@ const
|
||||||
kind: evmcCall,
|
kind: evmcCall,
|
||||||
depth: k.cpt.msg.depth + 1,
|
depth: k.cpt.msg.depth + 1,
|
||||||
gas: childGasLimit,
|
gas: childGasLimit,
|
||||||
sender: sender,
|
sender: p.sender,
|
||||||
contractAddress: contractAddress,
|
contractAddress: p.contractAddress,
|
||||||
codeAddress: destination,
|
codeAddress: p.destination,
|
||||||
value: value,
|
value: p.value,
|
||||||
data: k.cpt.memory.read(memInPos, memInLen),
|
data: k.cpt.memory.read(p.memInPos, p.memInLen),
|
||||||
flags: flags)
|
flags: p.flags)
|
||||||
|
|
||||||
var child = newComputation(k.cpt.vmState, msg)
|
var child = newComputation(k.cpt.vmState, msg)
|
||||||
k.cpt.chainTo(child):
|
k.cpt.chainTo(child):
|
||||||
|
@ -296,50 +298,28 @@ const
|
||||||
k.cpt.stack.top(1)
|
k.cpt.stack.top(1)
|
||||||
|
|
||||||
k.cpt.returnData = child.output
|
k.cpt.returnData = child.output
|
||||||
let actualOutputSize = min(memOutLen, child.output.len)
|
let actualOutputSize = min(p.memOutLen, child.output.len)
|
||||||
if actualOutputSize > 0:
|
if actualOutputSize > 0:
|
||||||
k.cpt.memory.write(memOutPos,
|
k.cpt.memory.write(p.memOutPos,
|
||||||
child.output.toOpenArray(0, actualOutputSize - 1))
|
child.output.toOpenArray(0, actualOutputSize - 1))
|
||||||
|
|
||||||
# ---------------------
|
# ---------------------
|
||||||
|
|
||||||
callCodeOp: Vm2OpFn = proc(k: Vm2Ctx) =
|
callCodeOp: Vm2OpFn = proc(k: Vm2Ctx) =
|
||||||
## 0xf2, Message-call into this account with an alternative account's code.
|
## 0xf2, Message-call into this account with an alternative account's code.
|
||||||
let (gas, value, destination, sender, memInPos, memInLen, memOutPos,
|
let
|
||||||
memOutLen, flags) = callCodeParams(k.cpt)
|
p = k.cpt.callCodeParams
|
||||||
|
|
||||||
let (memOffset, memLength) =
|
|
||||||
if calcMemSize(memInPos, memInLen) > calcMemSize(memOutPos, memOutLen):
|
|
||||||
(memInPos, memInLen)
|
|
||||||
else:
|
|
||||||
(memOutPos, memOutLen)
|
|
||||||
|
|
||||||
# EIP2929
|
|
||||||
# This came before old gas calculator
|
|
||||||
# because it will affect `k.cpt.gasMeter.gasRemaining`
|
|
||||||
# and further `childGasLimit`
|
|
||||||
if k.cpt.fork >= FkBerlin:
|
|
||||||
k.cpt.vmState.mutateStateDB:
|
|
||||||
if not db.inAccessList(destination):
|
|
||||||
db.accessList(destination)
|
|
||||||
# The WarmStorageReadCostEIP2929 (100) is already deducted in
|
|
||||||
# the form of a constant `gasCall`
|
|
||||||
k.cpt.gasMeter.consumeGas(
|
|
||||||
ColdAccountAccessCost - WarmStorageReadCost,
|
|
||||||
reason = "EIP2929 gasCall")
|
|
||||||
|
|
||||||
let contractAddress = k.cpt.msg.contractAddress
|
|
||||||
|
|
||||||
var (gasCost, childGasLimit) = k.cpt.gasCosts[CallCode].c_handler(
|
var (gasCost, childGasLimit) = k.cpt.gasCosts[CallCode].c_handler(
|
||||||
value,
|
p.value,
|
||||||
GasParams(
|
GasParams(
|
||||||
kind: CallCode,
|
kind: CallCode,
|
||||||
c_isNewAccount: not k.cpt.accountExists(contractAddress),
|
c_isNewAccount: not k.cpt.accountExists(p.contractAddress),
|
||||||
c_gasBalance: k.cpt.gasMeter.gasRemaining,
|
c_gasBalance: k.cpt.gasMeter.gasRemaining,
|
||||||
c_contractGas: gas,
|
c_contractGas: p.gas,
|
||||||
c_currentMemSize: k.cpt.memory.len,
|
c_currentMemSize: k.cpt.memory.len,
|
||||||
c_memOffset: memOffset,
|
c_memOffset: p.memOffset,
|
||||||
c_memLength: memLength))
|
c_memLength: p.memLength))
|
||||||
|
|
||||||
# EIP 2046: temporary disabled
|
# EIP 2046: temporary disabled
|
||||||
# reduce gas fee for precompiles
|
# reduce gas fee for precompiles
|
||||||
|
@ -364,11 +344,11 @@ const
|
||||||
raise newException(
|
raise newException(
|
||||||
OutOfGas, "Gas not enough to perform calculation (callCode)")
|
OutOfGas, "Gas not enough to perform calculation (callCode)")
|
||||||
|
|
||||||
k.cpt.memory.extend(memInPos, memInLen)
|
k.cpt.memory.extend(p.memInPos, p.memInLen)
|
||||||
k.cpt.memory.extend(memOutPos, memOutLen)
|
k.cpt.memory.extend(p.memOutPos, p.memOutLen)
|
||||||
|
|
||||||
let senderBalance = k.cpt.getBalance(sender)
|
let senderBalance = k.cpt.getBalance(p.sender)
|
||||||
if senderBalance < value:
|
if senderBalance < p.value:
|
||||||
debug "Insufficient funds",
|
debug "Insufficient funds",
|
||||||
available = senderBalance,
|
available = senderBalance,
|
||||||
needed = k.cpt.msg.value
|
needed = k.cpt.msg.value
|
||||||
|
@ -379,12 +359,12 @@ const
|
||||||
kind: evmcCallCode,
|
kind: evmcCallCode,
|
||||||
depth: k.cpt.msg.depth + 1,
|
depth: k.cpt.msg.depth + 1,
|
||||||
gas: childGasLimit,
|
gas: childGasLimit,
|
||||||
sender: sender,
|
sender: p.sender,
|
||||||
contractAddress: contractAddress,
|
contractAddress: p.contractAddress,
|
||||||
codeAddress: destination,
|
codeAddress: p.destination,
|
||||||
value: value,
|
value: p.value,
|
||||||
data: k.cpt.memory.read(memInPos, memInLen),
|
data: k.cpt.memory.read(p.memInPos, p.memInLen),
|
||||||
flags: flags)
|
flags: p.flags)
|
||||||
|
|
||||||
var child = newComputation(k.cpt.vmState, msg)
|
var child = newComputation(k.cpt.vmState, msg)
|
||||||
k.cpt.chainTo(child):
|
k.cpt.chainTo(child):
|
||||||
|
@ -396,9 +376,9 @@ const
|
||||||
k.cpt.stack.top(1)
|
k.cpt.stack.top(1)
|
||||||
|
|
||||||
k.cpt.returnData = child.output
|
k.cpt.returnData = child.output
|
||||||
let actualOutputSize = min(memOutLen, child.output.len)
|
let actualOutputSize = min(p.memOutLen, child.output.len)
|
||||||
if actualOutputSize > 0:
|
if actualOutputSize > 0:
|
||||||
k.cpt.memory.write(memOutPos,
|
k.cpt.memory.write(p.memOutPos,
|
||||||
child.output.toOpenArray(0, actualOutputSize - 1))
|
child.output.toOpenArray(0, actualOutputSize - 1))
|
||||||
|
|
||||||
# ---------------------
|
# ---------------------
|
||||||
|
@ -406,41 +386,19 @@ const
|
||||||
delegateCallOp: Vm2OpFn = proc(k: Vm2Ctx) =
|
delegateCallOp: Vm2OpFn = proc(k: Vm2Ctx) =
|
||||||
## 0xf4, Message-call into this account with an alternative account's
|
## 0xf4, Message-call into this account with an alternative account's
|
||||||
## code, but persisting the current values for sender and value.
|
## code, but persisting the current values for sender and value.
|
||||||
let (gas, value, destination, sender, memInPos, memInLen, memOutPos,
|
let
|
||||||
memOutLen, flags) = delegateCallParams(k.cpt)
|
p = k.cpt.delegateCallParams
|
||||||
|
|
||||||
let (memOffset, memLength) =
|
|
||||||
if calcMemSize(memInPos, memInLen) > calcMemSize(memOutPos, memOutLen):
|
|
||||||
(memInPos, memInLen)
|
|
||||||
else:
|
|
||||||
(memOutPos, memOutLen)
|
|
||||||
|
|
||||||
# EIP2929
|
|
||||||
# This came before old gas calculator
|
|
||||||
# because it will affect `k.cpt.gasMeter.gasRemaining`
|
|
||||||
# and further `childGasLimit`
|
|
||||||
if k.cpt.fork >= FkBerlin:
|
|
||||||
k.cpt.vmState.mutateStateDB:
|
|
||||||
if not db.inAccessList(destination):
|
|
||||||
db.accessList(destination)
|
|
||||||
# The WarmStorageReadCostEIP2929 (100) is already deducted in
|
|
||||||
# the form of a constant `gasCall`
|
|
||||||
k.cpt.gasMeter.consumeGas(
|
|
||||||
ColdAccountAccessCost - WarmStorageReadCost,
|
|
||||||
reason = "EIP2929 gasCall")
|
|
||||||
|
|
||||||
let contractAddress = k.cpt.msg.contractAddress
|
|
||||||
|
|
||||||
var (gasCost, childGasLimit) = k.cpt.gasCosts[DelegateCall].c_handler(
|
var (gasCost, childGasLimit) = k.cpt.gasCosts[DelegateCall].c_handler(
|
||||||
value,
|
p.value,
|
||||||
GasParams(
|
GasParams(
|
||||||
kind: DelegateCall,
|
kind: DelegateCall,
|
||||||
c_isNewAccount: not k.cpt.accountExists(contractAddress),
|
c_isNewAccount: not k.cpt.accountExists(p.contractAddress),
|
||||||
c_gasBalance: k.cpt.gasMeter.gasRemaining,
|
c_gasBalance: k.cpt.gasMeter.gasRemaining,
|
||||||
c_contractGas: gas,
|
c_contractGas: p.gas,
|
||||||
c_currentMemSize: k.cpt.memory.len,
|
c_currentMemSize: k.cpt.memory.len,
|
||||||
c_memOffset: memOffset,
|
c_memOffset: p.memOffset,
|
||||||
c_memLength: memLength))
|
c_memLength: p.memLength))
|
||||||
|
|
||||||
# EIP 2046: temporary disabled
|
# EIP 2046: temporary disabled
|
||||||
# reduce gas fee for precompiles
|
# reduce gas fee for precompiles
|
||||||
|
@ -461,19 +419,19 @@ const
|
||||||
raise newException(
|
raise newException(
|
||||||
OutOfGas, "Gas not enough to perform calculation (delegateCall)")
|
OutOfGas, "Gas not enough to perform calculation (delegateCall)")
|
||||||
|
|
||||||
k.cpt.memory.extend(memInPos, memInLen)
|
k.cpt.memory.extend(p.memInPos, p.memInLen)
|
||||||
k.cpt.memory.extend(memOutPos, memOutLen)
|
k.cpt.memory.extend(p.memOutPos, p.memOutLen)
|
||||||
|
|
||||||
let msg = Message(
|
let msg = Message(
|
||||||
kind: evmcDelegateCall,
|
kind: evmcDelegateCall,
|
||||||
depth: k.cpt.msg.depth + 1,
|
depth: k.cpt.msg.depth + 1,
|
||||||
gas: childGasLimit,
|
gas: childGasLimit,
|
||||||
sender: sender,
|
sender: p.sender,
|
||||||
contractAddress: contractAddress,
|
contractAddress: p.contractAddress,
|
||||||
codeAddress: destination,
|
codeAddress: p.destination,
|
||||||
value: value,
|
value: p.value,
|
||||||
data: k.cpt.memory.read(memInPos, memInLen),
|
data: k.cpt.memory.read(p.memInPos, p.memInLen),
|
||||||
flags: flags)
|
flags: p.flags)
|
||||||
|
|
||||||
var child = newComputation(k.cpt.vmState, msg)
|
var child = newComputation(k.cpt.vmState, msg)
|
||||||
k.cpt.chainTo(child):
|
k.cpt.chainTo(child):
|
||||||
|
@ -485,51 +443,29 @@ const
|
||||||
k.cpt.stack.top(1)
|
k.cpt.stack.top(1)
|
||||||
|
|
||||||
k.cpt.returnData = child.output
|
k.cpt.returnData = child.output
|
||||||
let actualOutputSize = min(memOutLen, child.output.len)
|
let actualOutputSize = min(p.memOutLen, child.output.len)
|
||||||
if actualOutputSize > 0:
|
if actualOutputSize > 0:
|
||||||
k.cpt.memory.write(memOutPos,
|
k.cpt.memory.write(p.memOutPos,
|
||||||
child.output.toOpenArray(0, actualOutputSize - 1))
|
child.output.toOpenArray(0, actualOutputSize - 1))
|
||||||
|
|
||||||
# ---------------------
|
# ---------------------
|
||||||
|
|
||||||
staticCallOp: Vm2OpFn = proc(k: Vm2Ctx) =
|
staticCallOp: Vm2OpFn = proc(k: Vm2Ctx) =
|
||||||
## 0xfa, Static message-call into an account.
|
## 0xfa, Static message-call into an account.
|
||||||
let (gas, value, destination, sender, memInPos, memInLen, memOutPos,
|
|
||||||
memOutLen, flags) = staticCallParams(k.cpt)
|
|
||||||
|
|
||||||
let (memOffset, memLength) =
|
let
|
||||||
if calcMemSize(memInPos, memInLen) > calcMemSize(memOutPos, memOutLen):
|
p = k.cpt.staticCallParams
|
||||||
(memInPos, memInLen)
|
|
||||||
else:
|
|
||||||
(memOutPos, memOutLen)
|
|
||||||
|
|
||||||
# EIP2929
|
|
||||||
# This came before old gas calculator
|
|
||||||
# because it will affect `k.cpt.gasMeter.gasRemaining`
|
|
||||||
# and further `childGasLimit`
|
|
||||||
if k.cpt.fork >= FkBerlin:
|
|
||||||
if k.cpt.fork >= FkBerlin:
|
|
||||||
k.cpt.vmState.mutateStateDB:
|
|
||||||
if not db.inAccessList(destination):
|
|
||||||
db.accessList(destination)
|
|
||||||
# The WarmStorageReadCostEIP2929 (100) is already deducted in
|
|
||||||
# the form of a constant `gasCall`
|
|
||||||
k.cpt.gasMeter.consumeGas(
|
|
||||||
ColdAccountAccessCost - WarmStorageReadCost,
|
|
||||||
reason = "EIP2929 gasCall")
|
|
||||||
|
|
||||||
let contractAddress = destination
|
|
||||||
|
|
||||||
var (gasCost, childGasLimit) = k.cpt.gasCosts[StaticCall].c_handler(
|
var (gasCost, childGasLimit) = k.cpt.gasCosts[StaticCall].c_handler(
|
||||||
value,
|
p.value,
|
||||||
GasParams(
|
GasParams(
|
||||||
kind: StaticCall,
|
kind: StaticCall,
|
||||||
c_isNewAccount: not k.cpt.accountExists(contractAddress),
|
c_isNewAccount: not k.cpt.accountExists(p.contractAddress),
|
||||||
c_gasBalance: k.cpt.gasMeter.gasRemaining,
|
c_gasBalance: k.cpt.gasMeter.gasRemaining,
|
||||||
c_contractGas: gas,
|
c_contractGas: p.gas,
|
||||||
c_currentMemSize: k.cpt.memory.len,
|
c_currentMemSize: k.cpt.memory.len,
|
||||||
c_memOffset: memOffset,
|
c_memOffset: p.memOffset,
|
||||||
c_memLength: memLength))
|
c_memLength: p.memLength))
|
||||||
|
|
||||||
# EIP 2046: temporary disabled
|
# EIP 2046: temporary disabled
|
||||||
# reduce gas fee for precompiles
|
# reduce gas fee for precompiles
|
||||||
|
@ -555,19 +491,19 @@ const
|
||||||
raise newException(
|
raise newException(
|
||||||
OutOfGas, "Gas not enough to perform calculation (staticCall)")
|
OutOfGas, "Gas not enough to perform calculation (staticCall)")
|
||||||
|
|
||||||
k.cpt.memory.extend(memInPos, memInLen)
|
k.cpt.memory.extend(p.memInPos, p.memInLen)
|
||||||
k.cpt.memory.extend(memOutPos, memOutLen)
|
k.cpt.memory.extend(p.memOutPos, p.memOutLen)
|
||||||
|
|
||||||
let msg = Message(
|
let msg = Message(
|
||||||
kind: evmcCall,
|
kind: evmcCall,
|
||||||
depth: k.cpt.msg.depth + 1,
|
depth: k.cpt.msg.depth + 1,
|
||||||
gas: childGasLimit,
|
gas: childGasLimit,
|
||||||
sender: sender,
|
sender: p.sender,
|
||||||
contractAddress: contractAddress,
|
contractAddress: p.contractAddress,
|
||||||
codeAddress: destination,
|
codeAddress: p.destination,
|
||||||
value: value,
|
value: p.value,
|
||||||
data: k.cpt.memory.read(memInPos, memInLen),
|
data: k.cpt.memory.read(p.memInPos, p.memInLen),
|
||||||
flags: flags)
|
flags: p.flags)
|
||||||
|
|
||||||
var child = newComputation(k.cpt.vmState, msg)
|
var child = newComputation(k.cpt.vmState, msg)
|
||||||
k.cpt.chainTo(child):
|
k.cpt.chainTo(child):
|
||||||
|
@ -579,9 +515,9 @@ const
|
||||||
k.cpt.stack.top(1)
|
k.cpt.stack.top(1)
|
||||||
|
|
||||||
k.cpt.returnData = child.output
|
k.cpt.returnData = child.output
|
||||||
let actualOutputSize = min(memOutLen, child.output.len)
|
let actualOutputSize = min(p.memOutLen, child.output.len)
|
||||||
if actualOutputSize > 0:
|
if actualOutputSize > 0:
|
||||||
k.cpt.memory.write(memOutPos,
|
k.cpt.memory.write(p.memOutPos,
|
||||||
child.output.toOpenArray(0, actualOutputSize - 1))
|
child.output.toOpenArray(0, actualOutputSize - 1))
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue