mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-02-23 09:18:29 +00:00
EVM gasCall values always stay on positive side (#2459)
* EVM gasCall values always stay on positive side This is also another part of preparations before converting GasInt to uint64 * Fix test_evm_support
This commit is contained in:
parent
c775c906a2
commit
4eaae5cbfa
@ -67,7 +67,8 @@ type
|
||||
|
||||
kind*: Op
|
||||
isNewAccount*: bool
|
||||
gasBalance*: GasInt
|
||||
gasLeft*: GasInt
|
||||
gasCallEIP2929*: GasInt
|
||||
contractGas*: UInt256
|
||||
currentMemSize*: GasNatural
|
||||
memOffset*: GasNatural
|
||||
@ -348,7 +349,6 @@ template gasCosts(fork: EVMFork, prefix, ResultGasCostsName: untyped) =
|
||||
static(4 * FeeSchedule[GasLogTopic])
|
||||
|
||||
func `prefix gasCall`(value: UInt256, params: GasParams): EvmResult[CallGasResult] {.nimcall.} =
|
||||
|
||||
# From the Yellow Paper, going through the equation from bottom to top
|
||||
# https://ethereum.github.io/yellowpaper/paper.pdf#appendix.H
|
||||
#
|
||||
@ -369,15 +369,18 @@ template gasCosts(fork: EVMFork, prefix, ResultGasCostsName: untyped) =
|
||||
# The discussion for the draft EIP-5, which proposes to change the CALL opcode also goes over
|
||||
# the current implementation - https://github.com/ethereum/EIPs/issues/8
|
||||
|
||||
# Both gasCost and childGasLimit can go below zero
|
||||
# but that is an OOG condition. Leaving this function
|
||||
# both of them are positive integers.
|
||||
# Both gasCost and childGasLimit are always on positive side
|
||||
|
||||
var gasCost: int64 = `prefix gasMemoryExpansion`(
|
||||
var gasLeft = params.gasLeft
|
||||
if gasLeft < params.gasCallEIP2929:
|
||||
return err(opErr(OutOfGas))
|
||||
gasLeft -= params.gasCallEIP2929
|
||||
|
||||
var gasCost: GasInt = `prefix gasMemoryExpansion`(
|
||||
params.currentMemSize,
|
||||
params.memOffset,
|
||||
params.memLength)
|
||||
var childGasLimit: int64
|
||||
var childGasLimit: GasInt
|
||||
|
||||
# Cnew_account
|
||||
if params.isNewAccount and params.kind == Call:
|
||||
@ -398,33 +401,34 @@ template gasCosts(fork: EVMFork, prefix, ResultGasCostsName: untyped) =
|
||||
# Cextra
|
||||
gasCost += static(FeeSchedule[GasCall])
|
||||
|
||||
if gasLeft < gasCost:
|
||||
return err(opErr(OutOfGas))
|
||||
gasLeft -= gasCost
|
||||
|
||||
# Cgascap
|
||||
when fork >= FkTangerine:
|
||||
# https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md
|
||||
let gas = `prefix all_but_one_64th`(params.gasBalance - gasCost)
|
||||
if params.contractGas > high(int64).u256 or
|
||||
gas < params.contractGas.truncate(int64):
|
||||
let gas = `prefix all_but_one_64th`(gasLeft)
|
||||
if params.contractGas > high(GasInt).u256 or
|
||||
gas < params.contractGas.truncate(GasInt):
|
||||
childGasLimit = gas
|
||||
else:
|
||||
childGasLimit = params.contractGas.truncate(int64)
|
||||
childGasLimit = params.contractGas.truncate(GasInt)
|
||||
else:
|
||||
if params.contractGas > high(int64).u256:
|
||||
if params.contractGas > high(GasInt).u256:
|
||||
return err(gasErr(GasIntOverflow))
|
||||
childGasLimit = params.contractGas.truncate(int64)
|
||||
childGasLimit = params.contractGas.truncate(GasInt)
|
||||
|
||||
if childGasLimit > 0: # skip check if childGasLimit is negative
|
||||
if gasCost.u256 + childGasLimit.u256 > high(int64).u256:
|
||||
return err(gasErr(GasIntOverflow))
|
||||
if gasCost.u256 + childGasLimit.u256 + params.gasCallEIP2929.u256 > high(GasInt).u256:
|
||||
return err(gasErr(GasIntOverflow))
|
||||
|
||||
gasCost += childGasLimit
|
||||
gasCost += params.gasCallEIP2929
|
||||
|
||||
# Ccallgas - Gas sent to the child message
|
||||
if not value.isZero and params.kind in {Call, CallCode}:
|
||||
childGasLimit += static(FeeSchedule[GasCallStipend])
|
||||
|
||||
if gasCost <= 0 and childGasLimit <= 0:
|
||||
return err(opErr(OutOfGas))
|
||||
|
||||
# at this point gasCost and childGasLimit is always > 0
|
||||
ok( (gasCost, childGasLimit) )
|
||||
|
||||
|
@ -210,21 +210,18 @@ proc callOp(k: var VmCtx): EvmResultVoid =
|
||||
|
||||
let
|
||||
p = ? cpt.callParams
|
||||
|
||||
var
|
||||
(gasCost, childGasLimit) = ? cpt.gasCosts[Call].c_handler(
|
||||
p.value,
|
||||
GasParams(
|
||||
kind: Call,
|
||||
isNewAccount: not cpt.accountExists(p.contractAddress),
|
||||
gasBalance: cpt.gasMeter.gasRemaining - p.gasCallEIP2929,
|
||||
gasLeft: cpt.gasMeter.gasRemaining,
|
||||
gasCallEIP2929: p.gasCallEIP2929,
|
||||
contractGas: p.gas,
|
||||
currentMemSize: cpt.memory.len,
|
||||
memOffset: p.memOffset,
|
||||
memLength: p.memLength))
|
||||
|
||||
# at this point gasCost is always > 0
|
||||
gasCost += p.gasCallEIP2929
|
||||
? cpt.opcodeGastCost(Call, gasCost, reason = $Call)
|
||||
|
||||
cpt.returnData.setLen(0)
|
||||
@ -285,21 +282,18 @@ proc callCodeOp(k: var VmCtx): EvmResultVoid =
|
||||
let
|
||||
cpt = k.cpt
|
||||
p = ? cpt.callCodeParams
|
||||
|
||||
var
|
||||
(gasCost, childGasLimit) = ? cpt.gasCosts[CallCode].c_handler(
|
||||
p.value,
|
||||
GasParams(
|
||||
kind: CallCode,
|
||||
isNewAccount: not cpt.accountExists(p.contractAddress),
|
||||
gasBalance: cpt.gasMeter.gasRemaining - p.gasCallEIP2929,
|
||||
gasLeft: cpt.gasMeter.gasRemaining,
|
||||
gasCallEIP2929: p.gasCallEIP2929,
|
||||
contractGas: p.gas,
|
||||
currentMemSize: cpt.memory.len,
|
||||
memOffset: p.memOffset,
|
||||
memLength: p.memLength))
|
||||
|
||||
# at this point gasCost is always > 0
|
||||
gasCost += p.gasCallEIP2929
|
||||
? cpt.opcodeGastCost(CallCode, gasCost, reason = $CallCode)
|
||||
|
||||
cpt.returnData.setLen(0)
|
||||
@ -361,21 +355,18 @@ proc delegateCallOp(k: var VmCtx): EvmResultVoid =
|
||||
let
|
||||
cpt = k.cpt
|
||||
p = ? cpt.delegateCallParams
|
||||
|
||||
var
|
||||
(gasCost, childGasLimit) = ? cpt.gasCosts[DelegateCall].c_handler(
|
||||
p.value,
|
||||
GasParams(
|
||||
kind: DelegateCall,
|
||||
isNewAccount: not cpt.accountExists(p.contractAddress),
|
||||
gasBalance: cpt.gasMeter.gasRemaining - p.gasCallEIP2929,
|
||||
gasLeft: cpt.gasMeter.gasRemaining,
|
||||
gasCallEIP2929: p.gasCallEIP2929,
|
||||
contractGas: p.gas,
|
||||
currentMemSize: cpt.memory.len,
|
||||
memOffset: p.memOffset,
|
||||
memLength: p.memLength))
|
||||
|
||||
# at this point gasCost is always > 0
|
||||
gasCost += p.gasCallEIP2929
|
||||
? cpt.opcodeGastCost(DelegateCall, gasCost, reason = $DelegateCall)
|
||||
|
||||
cpt.returnData.setLen(0)
|
||||
@ -431,21 +422,18 @@ proc staticCallOp(k: var VmCtx): EvmResultVoid =
|
||||
let
|
||||
cpt = k.cpt
|
||||
p = ? cpt.staticCallParams
|
||||
|
||||
var
|
||||
(gasCost, childGasLimit) = ? cpt.gasCosts[StaticCall].c_handler(
|
||||
p.value,
|
||||
GasParams(
|
||||
kind: StaticCall,
|
||||
isNewAccount: not cpt.accountExists(p.contractAddress),
|
||||
gasBalance: cpt.gasMeter.gasRemaining - p.gasCallEIP2929,
|
||||
gasLeft: cpt.gasMeter.gasRemaining,
|
||||
gasCallEIP2929: p.gasCallEIP2929,
|
||||
contractGas: p.gas,
|
||||
currentMemSize: cpt.memory.len,
|
||||
memOffset: p.memOffset,
|
||||
memLength: p.memLength))
|
||||
|
||||
# at this point gasCost is always > 0
|
||||
gasCost += p.gasCallEIP2929
|
||||
? cpt.opcodeGastCost(StaticCall, gasCost, reason = $StaticCall)
|
||||
|
||||
cpt.returnData.setLen(0)
|
||||
|
@ -381,7 +381,8 @@ proc runTestOverflow() =
|
||||
when defined(evmc_enabled):
|
||||
check res.error == "EVMC_FAILURE"
|
||||
else:
|
||||
check res.error == "Opcode Dispatch Error: GasIntOverflow, depth=1"
|
||||
# After gasCall values always on positive, this test become OOG
|
||||
check res.error == "Opcode Dispatch Error: OutOfGas, depth=1"
|
||||
|
||||
proc evmSupportMain*() =
|
||||
runStackTests()
|
||||
|
2
tools/t8n/testdata/00-521/exp.txt
vendored
2
tools/t8n/testdata/00-521/exp.txt
vendored
@ -12,6 +12,6 @@
|
||||
{"pc":8,"op":96,"gas":"0xf","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0"],"depth":2,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":10,"op":96,"gas":"0xc","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0"],"depth":2,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":12,"op":90,"gas":"0x9","gasCost":"0x2","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xfa"],"depth":2,"refund":0,"opName":"GAS"}
|
||||
{"pc":13,"op":241,"gas":"0x7","gasCost":"0x9","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xfa","0x7"],"depth":2,"refund":0,"opName":"CALL","error":"Opcode Dispatch Error: OutOfGas, depth=2"}
|
||||
{"pc":13,"op":241,"gas":"0x7","gasCost":"0x7","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xfa","0x7"],"depth":2,"refund":0,"opName":"CALL","error":"Opcode Dispatch Error: OutOfGas, depth=2"}
|
||||
{"pc":12,"op":80,"gas":"0x0","gasCost":"0x2","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"POP","error":"Opcode Dispatch Error: OutOfGas, depth=1"}
|
||||
{"output":"","gasUsed":"0xa54","error":"Opcode Dispatch Error: OutOfGas, depth=1"}
|
||||
|
Loading…
x
Reference in New Issue
Block a user