core/vm: add gas computation for EOFCREATE, EXT{CALL,DELEGATECALL,STATICCALL}
This commit is contained in:
parent
d206fba16d
commit
3d82fb13a3
|
@ -17,6 +17,7 @@
|
|||
package vm
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
|
@ -52,3 +53,32 @@ func callGas(isEip150 bool, availableGas, base uint64, callCost *uint256.Int) (u
|
|||
|
||||
return callCost.Uint64(), nil
|
||||
}
|
||||
|
||||
// extCallGas returns the actual gas cost for ext*call operations.
|
||||
//
|
||||
// EOF v1 includes EIP-150 rules (all but 1/64) with a floor of MIN_RETAINED_GAS (5000)
|
||||
// and a minimum returned value of MIN_CALLE_GASS (2300).
|
||||
// There is also no call gas, so all available gas is used.
|
||||
//
|
||||
// If the minimum retained gas constraint is violated, zero gas and no error is returned
|
||||
func extCallGas(availableGas, base uint64) (uint64, error) {
|
||||
if availableGas < base {
|
||||
return 0, ErrOutOfGas
|
||||
}
|
||||
availableGas = availableGas - base
|
||||
if availableGas < params.ExtCallMinRetainedGas {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
retainedGas := availableGas / 64
|
||||
if retainedGas < params.ExtCallMinRetainedGas {
|
||||
retainedGas = params.ExtCallMinRetainedGas
|
||||
}
|
||||
gas := availableGas - retainedGas
|
||||
|
||||
if gas < params.ExtCallMinCalleeGas {
|
||||
return 0, nil
|
||||
} else {
|
||||
return gas, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -504,18 +504,84 @@ func gasSelfdestruct(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me
|
|||
}
|
||||
|
||||
func gasExtCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||
panic("not implemented")
|
||||
var (
|
||||
gas uint64
|
||||
transfersValue = !stack.Back(3).IsZero()
|
||||
address = common.Address(stack.Back(0).Bytes20())
|
||||
overflow bool
|
||||
)
|
||||
if transfersValue {
|
||||
if evm.StateDB.Empty(address) {
|
||||
gas += params.CallNewAccountGas
|
||||
}
|
||||
if evm.chainRules.IsEIP4762 {
|
||||
gas, overflow = math.SafeAdd(gas, evm.AccessEvents.ValueTransferGas(contract.Address(), address))
|
||||
if overflow {
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
} else {
|
||||
gas += params.CallValueTransferGas
|
||||
}
|
||||
}
|
||||
memoryGas, err := memoryGasCost(mem, memorySize)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if gas, overflow = math.SafeAdd(gas, memoryGas); overflow {
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
|
||||
evm.callGasTemp, err = extCallGas(contract.Gas, gas)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
|
||||
return gas, nil
|
||||
}
|
||||
|
||||
func gasExtDelegateCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||
panic("not implemented")
|
||||
gas, err := memoryGasCost(mem, memorySize)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
evm.callGasTemp, err = extCallGas(contract.Gas, gas)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var overflow bool
|
||||
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
return gas, nil
|
||||
}
|
||||
|
||||
func gasExtStaticCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||
panic("not implemented")
|
||||
gas, err := memoryGasCost(mem, memorySize)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
evm.callGasTemp, err = extCallGas(contract.Gas, gas)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var overflow bool
|
||||
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
return gas, nil
|
||||
}
|
||||
|
||||
// gasEOFCreate returns the gas-cost for EOF-Create. Hashing charge needs to be
|
||||
// deducted in the opcode itself, since it depends on the immediate
|
||||
func gasEOFCreate(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||
panic("not implemented")
|
||||
gas, err := memoryGasCost(mem, memorySize)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// hashing charge needs to be deducted in the opcode itself, since it depends on the immediate
|
||||
return gas, nil
|
||||
}
|
||||
|
|
|
@ -89,6 +89,8 @@ const (
|
|||
CreateNGasEip4762 uint64 = 1000 // Once per CREATEn operations post-verkle
|
||||
SelfdestructRefundGas uint64 = 24000 // Refunded following a selfdestruct operation.
|
||||
MemoryGas uint64 = 3 // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
|
||||
ExtCallMinRetainedGas uint64 = 5000 // For EXT*CALL this is the minimum gas that the EIP158 1/64th rule must retain
|
||||
ExtCallMinCalleeGas uint64 = 2300 // For EXT*CALL this is the minimum gas that must be passed to the callee, ignoring 63/64
|
||||
|
||||
TxDataNonZeroGasFrontier uint64 = 68 // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions.
|
||||
TxDataNonZeroGasEIP2028 uint64 = 16 // Per byte of non zero data attached to a transaction after EIP 2028 (part in Istanbul)
|
||||
|
|
Loading…
Reference in New Issue