core/vm: interpreter loop generator PoC

This commit is contained in:
Ömer Faruk IRMAK 2025-07-21 11:49:21 +03:00
parent f17df6db91
commit ae63a92d08
8 changed files with 705 additions and 302 deletions

View file

@ -18,7 +18,7 @@ package vm
import ( import (
"fmt" "fmt"
"math" stdmath "math"
"sort" "sort"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -352,7 +352,7 @@ func opExtCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC
) )
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow() uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
if overflow { if overflow {
uint64CodeOffset = math.MaxUint64 uint64CodeOffset = stdmath.MaxUint64
} }
addr := common.Address(a.Bytes20()) addr := common.Address(a.Bytes20())
code := interpreter.evm.StateDB.GetCode(addr) code := interpreter.evm.StateDB.GetCode(addr)

View file

@ -64,8 +64,7 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
// MCOPY (stack position 2) // MCOPY (stack position 2)
// EXTCODECOPY (stack position 3) // EXTCODECOPY (stack position 3)
// RETURNDATACOPY (stack position 2) // RETURNDATACOPY (stack position 2)
func memoryCopierGas(stackpos int) gasFunc { func memoryCopierGas(stackpos int, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
// Gas for expanding the memory // Gas for expanding the memory
gas, err := memoryGasCost(mem, memorySize) gas, err := memoryGasCost(mem, memorySize)
if err != nil { if err != nil {
@ -85,16 +84,23 @@ func memoryCopierGas(stackpos int) gasFunc {
return 0, ErrGasUintOverflow return 0, ErrGasUintOverflow
} }
return gas, nil return gas, nil
}
} }
var ( func gasCallDataCopy(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
gasCallDataCopy = memoryCopierGas(2) return memoryCopierGas(2, evm, contract, stack, mem, memorySize)
gasCodeCopy = memoryCopierGas(2) }
gasMcopy = memoryCopierGas(2) func gasCodeCopy(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
gasExtCodeCopy = memoryCopierGas(3) return memoryCopierGas(2, evm, contract, stack, mem, memorySize)
gasReturnDataCopy = memoryCopierGas(2) }
) func gasMcopy(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return memoryCopierGas(2, evm, contract, stack, mem, memorySize)
}
func gasExtCodeCopy(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return memoryCopierGas(3, evm, contract, stack, mem, memorySize)
}
func gasReturnDataCopy(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return memoryCopierGas(2, evm, contract, stack, mem, memorySize)
}
func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var ( var (
@ -221,8 +227,7 @@ func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m
return params.SloadGasEIP2200, nil // dirty update (2.2) return params.SloadGasEIP2200, nil // dirty update (2.2)
} }
func makeGasLog(n uint64) gasFunc { func makeGasLog(n uint64, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
requestedSize, overflow := stack.Back(1).Uint64WithOverflow() requestedSize, overflow := stack.Back(1).Uint64WithOverflow()
if overflow { if overflow {
return 0, ErrGasUintOverflow return 0, ErrGasUintOverflow
@ -248,7 +253,22 @@ func makeGasLog(n uint64) gasFunc {
return 0, ErrGasUintOverflow return 0, ErrGasUintOverflow
} }
return gas, nil return gas, nil
} }
func gasLog0(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return makeGasLog(0, evm, contract, stack, mem, memorySize)
}
func gasLog1(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return makeGasLog(1, evm, contract, stack, mem, memorySize)
}
func gasLog2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return makeGasLog(2, evm, contract, stack, mem, memorySize)
}
func gasLog3(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return makeGasLog(3, evm, contract, stack, mem, memorySize)
}
func gasLog4(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return makeGasLog(4, evm, contract, stack, mem, memorySize)
} }
func gasKeccak256(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { func gasKeccak256(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {

217
core/vm/generator.go Normal file
View file

@ -0,0 +1,217 @@
package vm
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"io"
"os"
"reflect"
"runtime"
"strings"
)
var fSet = token.NewFileSet()
type opFuncNames struct {
memory string
gas string
execution string
}
func functionName(f any) string {
fValue := reflect.ValueOf(f)
if fValue.IsNil() {
return ""
}
rFunc := runtime.FuncForPC(fValue.Pointer())
if rFunc == nil {
panic(fmt.Sprint(f, "is not a function"))
}
ident := rFunc.Name()
arr := strings.Split(ident, ".")
return arr[len(arr)-1]
}
func collectFuncNames(jt JumpTable) [256]opFuncNames {
var funcNames [256]opFuncNames
for opCode, entry := range jt {
funcNames[opCode] = opFuncNames{
memory: functionName(entry.memorySize),
gas: functionName(entry.dynamicGas),
execution: functionName(entry.execute),
}
}
return funcNames
}
type funcDef struct {
decl *ast.FuncDecl
source string
}
type opFuncDefs struct {
memory funcDef
gas funcDef
execution funcDef
}
func definitionTargets(name string, funcNames *[256]opFuncNames, funcDefs *[256]opFuncDefs) []*funcDef {
targets := []*funcDef{}
for op := range funcNames {
if funcNames[op].memory == name {
targets = append(targets, &funcDefs[op].memory)
}
if funcNames[op].gas == name {
targets = append(targets, &funcDefs[op].gas)
}
if funcNames[op].execution == name {
targets = append(targets, &funcDefs[op].execution)
}
}
return targets
}
func extractBody(funcDef string) string {
start := strings.Index(funcDef, "{")
end := strings.LastIndex(funcDef, "}")
return funcDef[start : end+1]
}
func collectFuncDefinitions(funcNames [256]opFuncNames) [256]opFuncDefs {
pkgs, err := parser.ParseDir(fSet, ".", nil, 0)
if err != nil {
panic(fmt.Sprint("failed to parse vm package", err))
}
vmPkg := pkgs["vm"]
if vmPkg == nil {
panic(fmt.Sprint("vm package not found"))
}
var defs [256]opFuncDefs
for _, astFile := range vmPkg.Files {
f, err := os.Open(fSet.File(astFile.FileStart).Name())
if err != nil {
panic(fmt.Sprint("failed to open file package", astFile.Name.Name, err))
}
for _, decl := range astFile.Decls {
if fDecl, isFunc := decl.(*ast.FuncDecl); isFunc {
defTargets := definitionTargets(fDecl.Name.Name, &funcNames, &defs)
if len(defTargets) == 0 {
continue
}
declPos := fSet.Position(fDecl.Pos())
declEndPos := fSet.Position(fDecl.End())
declSize := declEndPos.Offset - declPos.Offset
def := make([]byte, declSize)
_, err := f.ReadAt(def, int64(declPos.Offset))
if err != nil && err != io.EOF {
panic(fmt.Sprint("failed to read function def", fDecl.Name.Name, err))
}
for _, defTarget := range defTargets {
(*defTarget) = funcDef{
source: string(def),
decl: fDecl,
}
}
}
}
}
return defs
}
func outputMemoryCalc(w io.Writer, op *funcDef) {
fmt.Fprintf(w, `
_memorySize, _overflow := func (stack *Stack) (uint64, bool) %s(callContext.Stack)
if _overflow {
return nil, ErrGasUintOverflow
}
`, extractBody(op.source))
}
func outputDynamicGas(w io.Writer, op *funcDef, hasDynamicMemory bool) {
dynamicMemory := "0"
if hasDynamicMemory {
dynamicMemory = "_memorySize"
}
fmt.Fprintf(w, `
_dynamicGas, _gasErr := func (evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) %s(interpreter.evm, callContext.Contract, callContext.Stack, callContext.Memory, %s)
if _gasErr != nil {
return nil, ErrOutOfGas
}
if !callContext.Contract.UseGas(_dynamicGas, nil, tracing.GasChangeIgnored) {
return nil, ErrOutOfGas
}
`, extractBody(op.source), dynamicMemory)
if hasDynamicMemory {
fmt.Fprintf(w, "callContext.Memory.Resize(_memorySize)\n")
}
}
func outputExecution(w io.Writer, op *funcDef) {
fmt.Fprintf(w, `
_, _executionErr := func (pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) %s(&pc, interpreter, callContext)
if _executionErr != nil {
return nil, _executionErr
}
`, extractBody(op.source))
}
func GenerateRun() {
set := newLondonInstructionSet()
funcNames := collectFuncNames(set)
funcDefinitions := collectFuncDefinitions(funcNames)
output, _ := os.Create("out.go")
fmt.Fprintln(output, `package vm
func Run(interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) {
var pc uint64
for {
op := callContext.Contract.GetOp(pc)
switch op {
`)
for opCode := range funcDefinitions {
fmt.Fprintf(output, `case %d:
if !callContext.Contract.UseGas(%d, nil, tracing.GasChangeIgnored) {
return nil, ErrOutOfGas
}
if sLen := callContext.Stack.len(); sLen < %d {
return nil, &ErrStackUnderflow{stackLen: sLen, required: %d}
} else if sLen > %d {
return nil, &ErrStackOverflow{stackLen: sLen, limit: %d}
}
`, opCode, set[opCode].constantGas, set[opCode].minStack, set[opCode].minStack, set[opCode].maxStack, set[opCode].maxStack)
if funcDefinitions[opCode].memory.decl != nil {
outputMemoryCalc(output, &funcDefinitions[opCode].memory)
} else if len(funcNames[opCode].memory) > 0 {
panic(fmt.Sprint("failed to get memory handler definition for ", opCodeToString[opCode]))
}
if funcDefinitions[opCode].gas.decl != nil {
outputDynamicGas(output, &funcDefinitions[opCode].gas, funcDefinitions[opCode].memory.decl != nil)
} else if len(funcNames[opCode].gas) > 0 {
panic(fmt.Sprint("failed to get gas handler definition for ", opCodeToString[opCode]))
}
if funcDefinitions[opCode].execution.decl != nil {
outputExecution(output, &funcDefinitions[opCode].execution)
} else if len(funcNames[opCode].execution) > 0 {
panic(fmt.Sprint("failed to get exec handler definition for ", opCodeToString[opCode]))
}
}
fmt.Fprintln(output, `}
pc++
}}`)
output.Close()
}

View file

@ -17,7 +17,7 @@
package vm package vm
import ( import (
"math" stdmath "math"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/tracing"
@ -296,7 +296,7 @@ func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
) )
dataOffset64, overflow := dataOffset.Uint64WithOverflow() dataOffset64, overflow := dataOffset.Uint64WithOverflow()
if overflow { if overflow {
dataOffset64 = math.MaxUint64 dataOffset64 = stdmath.MaxUint64
} }
// These values are checked for overflow during gas cost calculation // These values are checked for overflow during gas cost calculation
memOffset64 := memOffset.Uint64() memOffset64 := memOffset.Uint64()
@ -352,7 +352,7 @@ func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
) )
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow() uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
if overflow { if overflow {
uint64CodeOffset = math.MaxUint64 uint64CodeOffset = stdmath.MaxUint64
} }
codeCopy := getData(scope.Contract.Code, uint64CodeOffset, length.Uint64()) codeCopy := getData(scope.Contract.Code, uint64CodeOffset, length.Uint64())
@ -370,7 +370,7 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
) )
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow() uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
if overflow { if overflow {
uint64CodeOffset = math.MaxUint64 uint64CodeOffset = stdmath.MaxUint64
} }
addr := common.Address(a.Bytes20()) addr := common.Address(a.Bytes20())
code := interpreter.evm.StateDB.GetCode(addr) code := interpreter.evm.StateDB.GetCode(addr)
@ -924,8 +924,7 @@ func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeCon
// following functions are used by the instruction jump table // following functions are used by the instruction jump table
// make log instruction function // make log instruction function
func makeLog(size int) executionFunc { func doLog(size int, pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
if interpreter.readOnly { if interpreter.readOnly {
return nil, ErrWriteProtection return nil, ErrWriteProtection
} }
@ -948,7 +947,22 @@ func makeLog(size int) executionFunc {
}) })
return nil, nil return nil, nil
} }
func opLog0(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doLog(0, pc, interpreter, scope)
}
func opLog1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doLog(1, pc, interpreter, scope)
}
func opLog2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doLog(2, pc, interpreter, scope)
}
func opLog3(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doLog(3, pc, interpreter, scope)
}
func opLog4(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doLog(4, pc, interpreter, scope)
} }
// opPush1 is a specialized version of pushN // opPush1 is a specialized version of pushN
@ -983,10 +997,9 @@ func opPush2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
return nil, nil return nil, nil
} }
// make push instruction function func doPush(size uint64, pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
func makePush(size uint64, pushByteSize int) executionFunc {
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
var ( var (
pushByteSize = int(size)
codeLen = len(scope.Contract.Code) codeLen = len(scope.Contract.Code)
start = min(codeLen, int(*pc+1)) start = min(codeLen, int(*pc+1))
end = min(codeLen, start+pushByteSize) end = min(codeLen, start+pushByteSize)
@ -1000,13 +1013,160 @@ func makePush(size uint64, pushByteSize int) executionFunc {
scope.Stack.push(a) scope.Stack.push(a)
*pc += size *pc += size
return nil, nil return nil, nil
}
} }
// make dup instruction function func opPush3(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
func makeDup(size int64) executionFunc { return doPush(3, pc, interpreter, scope)
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { }
scope.Stack.dup(int(size)) func opPush4(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return nil, nil return doPush(4, pc, interpreter, scope)
} }
func opPush5(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(5, pc, interpreter, scope)
}
func opPush6(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(6, pc, interpreter, scope)
}
func opPush7(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(7, pc, interpreter, scope)
}
func opPush8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(8, pc, interpreter, scope)
}
func opPush9(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(9, pc, interpreter, scope)
}
func opPush10(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(10, pc, interpreter, scope)
}
func opPush11(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(11, pc, interpreter, scope)
}
func opPush12(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(12, pc, interpreter, scope)
}
func opPush13(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(13, pc, interpreter, scope)
}
func opPush14(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(14, pc, interpreter, scope)
}
func opPush15(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(15, pc, interpreter, scope)
}
func opPush16(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(16, pc, interpreter, scope)
}
func opPush17(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(17, pc, interpreter, scope)
}
func opPush18(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(18, pc, interpreter, scope)
}
func opPush19(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(19, pc, interpreter, scope)
}
func opPush20(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(20, pc, interpreter, scope)
}
func opPush21(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(21, pc, interpreter, scope)
}
func opPush22(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(22, pc, interpreter, scope)
}
func opPush23(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(23, pc, interpreter, scope)
}
func opPush24(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(24, pc, interpreter, scope)
}
func opPush25(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(25, pc, interpreter, scope)
}
func opPush26(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(26, pc, interpreter, scope)
}
func opPush27(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(27, pc, interpreter, scope)
}
func opPush28(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(28, pc, interpreter, scope)
}
func opPush29(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(29, pc, interpreter, scope)
}
func opPush30(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(30, pc, interpreter, scope)
}
func opPush31(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(31, pc, interpreter, scope)
}
func opPush32(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return doPush(32, pc, interpreter, scope)
}
func opDup1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(1)
return nil, nil
}
func opDup2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(2)
return nil, nil
}
func opDup3(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(3)
return nil, nil
}
func opDup4(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(4)
return nil, nil
}
func opDup5(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(5)
return nil, nil
}
func opDup6(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(6)
return nil, nil
}
func opDup7(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(7)
return nil, nil
}
func opDup8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(8)
return nil, nil
}
func opDup9(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(9)
return nil, nil
}
func opDup10(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(10)
return nil, nil
}
func opDup11(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(11)
return nil, nil
}
func opDup12(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(12)
return nil, nil
}
func opDup13(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(13)
return nil, nil
}
func opDup14(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(14)
return nil, nil
}
func opDup15(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(15)
return nil, nil
}
func opDup16(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(16)
return nil, nil
} }

View file

@ -906,7 +906,7 @@ func TestOpMCopy(t *testing.T) {
func TestPush(t *testing.T) { func TestPush(t *testing.T) {
code := common.FromHex("0011223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121") code := common.FromHex("0011223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121")
push32 := makePush(32, 32) push32 := opPush32
scope := &ScopeContext{ scope := &ScopeContext{
Memory: nil, Memory: nil,

View file

@ -88,7 +88,6 @@ func BenchmarkInterpreter(b *testing.B) {
) )
stack.push(uint256.NewInt(123)) stack.push(uint256.NewInt(123))
stack.push(uint256.NewInt(123)) stack.push(uint256.NewInt(123))
gasSStoreEIP3529 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP3529)
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
gasSStoreEIP3529(evm, contract, stack, mem, 1234) gasSStoreEIP3529(evm, contract, stack, mem, 1234)

View file

@ -633,277 +633,277 @@ func newFrontierInstructionSet() JumpTable {
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH3: { PUSH3: {
execute: makePush(3, 3), execute: opPush3,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH4: { PUSH4: {
execute: makePush(4, 4), execute: opPush4,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH5: { PUSH5: {
execute: makePush(5, 5), execute: opPush5,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH6: { PUSH6: {
execute: makePush(6, 6), execute: opPush6,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH7: { PUSH7: {
execute: makePush(7, 7), execute: opPush7,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH8: { PUSH8: {
execute: makePush(8, 8), execute: opPush8,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH9: { PUSH9: {
execute: makePush(9, 9), execute: opPush9,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH10: { PUSH10: {
execute: makePush(10, 10), execute: opPush10,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH11: { PUSH11: {
execute: makePush(11, 11), execute: opPush11,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH12: { PUSH12: {
execute: makePush(12, 12), execute: opPush12,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH13: { PUSH13: {
execute: makePush(13, 13), execute: opPush13,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH14: { PUSH14: {
execute: makePush(14, 14), execute: opPush14,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH15: { PUSH15: {
execute: makePush(15, 15), execute: opPush15,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH16: { PUSH16: {
execute: makePush(16, 16), execute: opPush16,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH17: { PUSH17: {
execute: makePush(17, 17), execute: opPush17,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH18: { PUSH18: {
execute: makePush(18, 18), execute: opPush18,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH19: { PUSH19: {
execute: makePush(19, 19), execute: opPush19,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH20: { PUSH20: {
execute: makePush(20, 20), execute: opPush20,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH21: { PUSH21: {
execute: makePush(21, 21), execute: opPush21,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH22: { PUSH22: {
execute: makePush(22, 22), execute: opPush22,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH23: { PUSH23: {
execute: makePush(23, 23), execute: opPush23,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH24: { PUSH24: {
execute: makePush(24, 24), execute: opPush24,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH25: { PUSH25: {
execute: makePush(25, 25), execute: opPush25,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH26: { PUSH26: {
execute: makePush(26, 26), execute: opPush26,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH27: { PUSH27: {
execute: makePush(27, 27), execute: opPush27,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH28: { PUSH28: {
execute: makePush(28, 28), execute: opPush28,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH29: { PUSH29: {
execute: makePush(29, 29), execute: opPush29,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH30: { PUSH30: {
execute: makePush(30, 30), execute: opPush30,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH31: { PUSH31: {
execute: makePush(31, 31), execute: opPush31,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
PUSH32: { PUSH32: {
execute: makePush(32, 32), execute: opPush32,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minStack(0, 1), minStack: minStack(0, 1),
maxStack: maxStack(0, 1), maxStack: maxStack(0, 1),
}, },
DUP1: { DUP1: {
execute: makeDup(1), execute: opDup1,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(1), minStack: minDupStack(1),
maxStack: maxDupStack(1), maxStack: maxDupStack(1),
}, },
DUP2: { DUP2: {
execute: makeDup(2), execute: opDup2,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(2), minStack: minDupStack(2),
maxStack: maxDupStack(2), maxStack: maxDupStack(2),
}, },
DUP3: { DUP3: {
execute: makeDup(3), execute: opDup3,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(3), minStack: minDupStack(3),
maxStack: maxDupStack(3), maxStack: maxDupStack(3),
}, },
DUP4: { DUP4: {
execute: makeDup(4), execute: opDup4,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(4), minStack: minDupStack(4),
maxStack: maxDupStack(4), maxStack: maxDupStack(4),
}, },
DUP5: { DUP5: {
execute: makeDup(5), execute: opDup5,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(5), minStack: minDupStack(5),
maxStack: maxDupStack(5), maxStack: maxDupStack(5),
}, },
DUP6: { DUP6: {
execute: makeDup(6), execute: opDup6,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(6), minStack: minDupStack(6),
maxStack: maxDupStack(6), maxStack: maxDupStack(6),
}, },
DUP7: { DUP7: {
execute: makeDup(7), execute: opDup7,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(7), minStack: minDupStack(7),
maxStack: maxDupStack(7), maxStack: maxDupStack(7),
}, },
DUP8: { DUP8: {
execute: makeDup(8), execute: opDup8,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(8), minStack: minDupStack(8),
maxStack: maxDupStack(8), maxStack: maxDupStack(8),
}, },
DUP9: { DUP9: {
execute: makeDup(9), execute: opDup9,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(9), minStack: minDupStack(9),
maxStack: maxDupStack(9), maxStack: maxDupStack(9),
}, },
DUP10: { DUP10: {
execute: makeDup(10), execute: opDup10,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(10), minStack: minDupStack(10),
maxStack: maxDupStack(10), maxStack: maxDupStack(10),
}, },
DUP11: { DUP11: {
execute: makeDup(11), execute: opDup11,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(11), minStack: minDupStack(11),
maxStack: maxDupStack(11), maxStack: maxDupStack(11),
}, },
DUP12: { DUP12: {
execute: makeDup(12), execute: opDup12,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(12), minStack: minDupStack(12),
maxStack: maxDupStack(12), maxStack: maxDupStack(12),
}, },
DUP13: { DUP13: {
execute: makeDup(13), execute: opDup13,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(13), minStack: minDupStack(13),
maxStack: maxDupStack(13), maxStack: maxDupStack(13),
}, },
DUP14: { DUP14: {
execute: makeDup(14), execute: opDup14,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(14), minStack: minDupStack(14),
maxStack: maxDupStack(14), maxStack: maxDupStack(14),
}, },
DUP15: { DUP15: {
execute: makeDup(15), execute: opDup15,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(15), minStack: minDupStack(15),
maxStack: maxDupStack(15), maxStack: maxDupStack(15),
}, },
DUP16: { DUP16: {
execute: makeDup(16), execute: opDup16,
constantGas: GasFastestStep, constantGas: GasFastestStep,
minStack: minDupStack(16), minStack: minDupStack(16),
maxStack: maxDupStack(16), maxStack: maxDupStack(16),
@ -1005,36 +1005,36 @@ func newFrontierInstructionSet() JumpTable {
maxStack: maxSwapStack(17), maxStack: maxSwapStack(17),
}, },
LOG0: { LOG0: {
execute: makeLog(0), execute: opLog0,
dynamicGas: makeGasLog(0), dynamicGas: gasLog0,
minStack: minStack(2, 0), minStack: minStack(2, 0),
maxStack: maxStack(2, 0), maxStack: maxStack(2, 0),
memorySize: memoryLog, memorySize: memoryLog,
}, },
LOG1: { LOG1: {
execute: makeLog(1), execute: opLog1,
dynamicGas: makeGasLog(1), dynamicGas: gasLog1,
minStack: minStack(3, 0), minStack: minStack(3, 0),
maxStack: maxStack(3, 0), maxStack: maxStack(3, 0),
memorySize: memoryLog, memorySize: memoryLog,
}, },
LOG2: { LOG2: {
execute: makeLog(2), execute: opLog2,
dynamicGas: makeGasLog(2), dynamicGas: gasLog2,
minStack: minStack(4, 0), minStack: minStack(4, 0),
maxStack: maxStack(4, 0), maxStack: maxStack(4, 0),
memorySize: memoryLog, memorySize: memoryLog,
}, },
LOG3: { LOG3: {
execute: makeLog(3), execute: opLog3,
dynamicGas: makeGasLog(3), dynamicGas: gasLog3,
minStack: minStack(5, 0), minStack: minStack(5, 0),
maxStack: maxStack(5, 0), maxStack: maxStack(5, 0),
memorySize: memoryLog, memorySize: memoryLog,
}, },
LOG4: { LOG4: {
execute: makeLog(4), execute: opLog4,
dynamicGas: makeGasLog(4), dynamicGas: gasLog4,
minStack: minStack(6, 0), minStack: minStack(6, 0),
maxStack: maxStack(6, 0), maxStack: maxStack(6, 0),
memorySize: memoryLog, memorySize: memoryLog,

View file

@ -26,8 +26,7 @@ import (
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
func makeGasSStoreFunc(clearingRefund uint64) gasFunc { func gasSStoreFuncEIP(clearingRefund uint64, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
// If we fail the minimum gas availability invariant, fail (0) // If we fail the minimum gas availability invariant, fail (0)
if contract.Gas <= params.SstoreSentryGasEIP2200 { if contract.Gas <= params.SstoreSentryGasEIP2200 {
return 0, errors.New("not enough gas for reentrancy sentry") return 0, errors.New("not enough gas for reentrancy sentry")
@ -87,7 +86,6 @@ func makeGasSStoreFunc(clearingRefund uint64) gasFunc {
// EIP-2200 original clause: // EIP-2200 original clause:
//return params.SloadGasEIP2200, nil // dirty update (2.2) //return params.SloadGasEIP2200, nil // dirty update (2.2)
return cost + params.WarmStorageReadCostEIP2929, nil // dirty update (2.2) return cost + params.WarmStorageReadCostEIP2929, nil // dirty update (2.2)
}
} }
// gasSLoadEIP2929 calculates dynamic gas for SLOAD according to EIP-2929 // gasSLoadEIP2929 calculates dynamic gas for SLOAD according to EIP-2929
@ -152,8 +150,7 @@ func gasEip2929AccountCheck(evm *EVM, contract *Contract, stack *Stack, mem *Mem
return 0, nil return 0, nil
} }
func makeCallVariantGasCallEIP2929(oldCalculator gasFunc, addressPosition int) gasFunc { func makeCallVariantGasCallEIP2929(oldCalculator gasFunc, addressPosition int, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
addr := common.Address(stack.Back(addressPosition).Bytes20()) addr := common.Address(stack.Back(addressPosition).Bytes20())
// Check slot presence in the access list // Check slot presence in the access list
warmAccess := evm.StateDB.AddressInAccessList(addr) warmAccess := evm.StateDB.AddressInAccessList(addr)
@ -188,40 +185,52 @@ func makeCallVariantGasCallEIP2929(oldCalculator gasFunc, addressPosition int) g
return 0, ErrGasUintOverflow return 0, ErrGasUintOverflow
} }
return gas, nil return gas, nil
}
} }
var ( func gasCallEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
gasCallEIP2929 = makeCallVariantGasCallEIP2929(gasCall, 1) return makeCallVariantGasCallEIP2929(gasCall, 1, evm, contract, stack, mem, memorySize)
gasDelegateCallEIP2929 = makeCallVariantGasCallEIP2929(gasDelegateCall, 1) }
gasStaticCallEIP2929 = makeCallVariantGasCallEIP2929(gasStaticCall, 1) func gasDelegateCallEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
gasCallCodeEIP2929 = makeCallVariantGasCallEIP2929(gasCallCode, 1) return makeCallVariantGasCallEIP2929(gasDelegateCall, 1, evm, contract, stack, mem, memorySize)
gasSelfdestructEIP2929 = makeSelfdestructGasFn(true) }
// gasSelfdestructEIP3529 implements the changes in EIP-3529 (no refunds) func gasStaticCallEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
gasSelfdestructEIP3529 = makeSelfdestructGasFn(false) return makeCallVariantGasCallEIP2929(gasStaticCall, 1, evm, contract, stack, mem, memorySize)
}
func gasCallCodeEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return makeCallVariantGasCallEIP2929(gasCallCode, 1, evm, contract, stack, mem, memorySize)
}
func gasSelfdestructEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return makeSelfdestructGasFn(true, evm, contract, stack, mem, memorySize)
}
func gasSelfdestructEIP3529(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return makeSelfdestructGasFn(false, evm, contract, stack, mem, memorySize)
}
// gasSStoreEIP2929 implements gas cost for SSTORE according to EIP-2929 // gasSStoreEIP2929 implements gas cost for SSTORE according to EIP-2929
// //
// When calling SSTORE, check if the (address, storage_key) pair is in accessed_storage_keys. // When calling SSTORE, check if the (address, storage_key) pair is in accessed_storage_keys.
// If it is not, charge an additional COLD_SLOAD_COST gas, and add the pair to accessed_storage_keys. // If it is not, charge an additional COLD_SLOAD_COST gas, and add the pair to accessed_storage_keys.
// Additionally, modify the parameters defined in EIP 2200 as follows: // Additionally, modify the parameters defined in EIP 2200 as follows:
// //
// Parameter Old value New value // Parameter Old value New value
// SLOAD_GAS 800 = WARM_STORAGE_READ_COST // SLOAD_GAS 800 = WARM_STORAGE_READ_COST
// SSTORE_RESET_GAS 5000 5000 - COLD_SLOAD_COST // SSTORE_RESET_GAS 5000 5000 - COLD_SLOAD_COST
// //
//The other parameters defined in EIP 2200 are unchanged. // The other parameters defined in EIP 2200 are unchanged.
// see gasSStoreEIP2200(...) in core/vm/gas_table.go for more info about how EIP 2200 is specified // see gasSStoreEIP2200(...) in core/vm/gas_table.go for more info about how EIP 2200 is specified
gasSStoreEIP2929 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP2200) func gasSStoreEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
return gasSStoreFuncEIP(params.SstoreClearsScheduleRefundEIP2200, evm, contract, stack, mem, memorySize)
}
// gasSStoreEIP3529 implements gas cost for SSTORE according to EIP-3529 // gasSStoreEIP3529 implements gas cost for SSTORE according to EIP-3529
// Replace `SSTORE_CLEARS_SCHEDULE` with `SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST` (4,800) // Replace `SSTORE_CLEARS_SCHEDULE` with `SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST` (4,800)
gasSStoreEIP3529 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP3529) func gasSStoreEIP3529(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
) return gasSStoreFuncEIP(params.SstoreClearsScheduleRefundEIP3529, evm, contract, stack, mem, memorySize)
}
// makeSelfdestructGasFn can create the selfdestruct dynamic gas function for EIP-2929 and EIP-3529 // makeSelfdestructGasFn can create the selfdestruct dynamic gas function for EIP-2929 and EIP-3529
func makeSelfdestructGasFn(refundsEnabled bool) gasFunc { func makeSelfdestructGasFn(refundsEnabled bool, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
gasFunc := func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var ( var (
gas uint64 gas uint64
address = common.Address(stack.peek().Bytes20()) address = common.Address(stack.peek().Bytes20())
@ -239,8 +248,6 @@ func makeSelfdestructGasFn(refundsEnabled bool) gasFunc {
evm.StateDB.AddRefund(params.SelfdestructRefundGas) evm.StateDB.AddRefund(params.SelfdestructRefundGas)
} }
return gas, nil return gas, nil
}
return gasFunc
} }
var ( var (