core/vm: PAY opcode EIP-5920

This commit is contained in:
Sina Mahmoodi 2024-03-18 17:04:29 +01:00
parent ba2dd9385c
commit 4ed9a49e9d
4 changed files with 48 additions and 1 deletions

View file

@ -37,6 +37,7 @@ var activators = map[int]func(*JumpTable){
1884: enable1884, 1884: enable1884,
1344: enable1344, 1344: enable1344,
1153: enable1153, 1153: enable1153,
5920: enable5920,
} }
// EnableEIP enables the given EIP on the config. // EnableEIP enables the given EIP on the config.
@ -55,6 +56,7 @@ func ValidEip(eipNum int) bool {
_, ok := activators[eipNum] _, ok := activators[eipNum]
return ok return ok
} }
func ActivateableEips() []string { func ActivateableEips() []string {
var nums []string var nums []string
for k := range activators { for k := range activators {
@ -319,3 +321,27 @@ func enable6780(jt *JumpTable) {
maxStack: maxStack(1, 0), maxStack: maxStack(1, 0),
} }
} }
func enable5920(jt *JumpTable) {
jt[PAY] = &operation{
execute: opPay,
constantGas: params.WarmStorageReadCostEIP2929,
dynamicGas: gasPay,
minStack: minStack(2, 0),
maxStack: maxStack(2, 0),
}
}
func opPay(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
if interpreter.readOnly {
return nil, ErrWriteProtection
}
var (
addr = scope.Stack.pop()
amount = scope.Stack.pop()
)
if interpreter.evm.Context.CanTransfer(interpreter.evm.StateDB, scope.Contract.Address(), &amount) {
interpreter.evm.Context.Transfer(interpreter.evm.StateDB, scope.Contract.Address(), addr.Bytes20(), &amount)
}
return nil, nil
}

View file

@ -477,3 +477,21 @@ func gasSelfdestruct(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me
} }
return gas, nil return gas, nil
} }
func gasPay(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var (
addr = stack.peek().Bytes20()
transfersValue = !stack.Back(1).IsZero()
)
gas, err := gasEip2929AccountCheck(evm, contract, stack, mem, memorySize)
if err != nil {
return 0, err
}
if transfersValue {
gas += params.CallValueTransferGas
if evm.StateDB.Empty(addr) {
gas += params.CallNewAccountGas
}
}
return gas, nil
}

View file

@ -189,7 +189,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
return nil, ErrOutOfGas return nil, ErrOutOfGas
} }
if operation.dynamicGas != nil { if operation.dynamicGas != nil {
// All ops with a dynamic memory usage also has a dynamic gas cost. // All ops with a dynamic memory usage also have a dynamic gas cost.
var memorySize uint64 var memorySize uint64
// calculate the new memory size and expand the memory to fit // calculate the new memory size and expand the memory to fit
// the operation // the operation

View file

@ -218,6 +218,7 @@ const (
DELEGATECALL OpCode = 0xf4 DELEGATECALL OpCode = 0xf4
CREATE2 OpCode = 0xf5 CREATE2 OpCode = 0xf5
PAY OpCode = 0xf9
STATICCALL OpCode = 0xfa STATICCALL OpCode = 0xfa
REVERT OpCode = 0xfd REVERT OpCode = 0xfd
INVALID OpCode = 0xfe INVALID OpCode = 0xfe
@ -391,6 +392,7 @@ var opCodeToString = [256]string{
CALLCODE: "CALLCODE", CALLCODE: "CALLCODE",
DELEGATECALL: "DELEGATECALL", DELEGATECALL: "DELEGATECALL",
CREATE2: "CREATE2", CREATE2: "CREATE2",
PAY: "PAY",
STATICCALL: "STATICCALL", STATICCALL: "STATICCALL",
REVERT: "REVERT", REVERT: "REVERT",
INVALID: "INVALID", INVALID: "INVALID",
@ -554,6 +556,7 @@ var stringToOp = map[string]OpCode{
"REVERT": REVERT, "REVERT": REVERT,
"INVALID": INVALID, "INVALID": INVALID,
"SELFDESTRUCT": SELFDESTRUCT, "SELFDESTRUCT": SELFDESTRUCT,
"PAY": PAY,
} }
// StringToOp finds the opcode whose name is stored in `str`. // StringToOp finds the opcode whose name is stored in `str`.