Skip to content

Commit

Permalink
CREATE3 impl
Browse files Browse the repository at this point in the history
  • Loading branch information
racytech committed Nov 21, 2023
1 parent 1292572 commit a48e4fe
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 44 deletions.
71 changes: 71 additions & 0 deletions core/vm/eips.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,23 @@ func enableEOF(jt *JumpTable) {
numPush: 0,
memorySize: memoryDataCopy,
}
jt[CREATE3] = &operation{
execute: opCreate3,
constantGas: params.Create3Gas,
// dynamicGas: gasCreate2,
numPop: 4,
numPush: 1,
memorySize: memoryCreate2,
}
jt[CREATE4] = &operation{
execute: opCreate4,
constantGas: params.Create4Gas,
// dynamicGas: gasCreate2,
numPop: 4,
numPush: 1,
memorySize: memoryCreate2,
}
jt[RETURNCONTRACT] = &operation{}
}

// opRjump implements the rjump opcode.
Expand Down Expand Up @@ -587,3 +604,57 @@ func opDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([

return nil, nil
}

func opCreate3(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
if interpreter.readOnly {
return nil, ErrWriteProtection
}
var (
code = scope.Contract.CodeAt(scope.CodeSection)
initContainerIdx = int(code[*pc+1])
endowment = scope.Stack.Pop()
salt = scope.Stack.Pop()
offset, size = scope.Stack.Pop(), scope.Stack.Pop()
inputOffset = offset.Uint64()
inputSize = size.Uint64()
gas = scope.Contract.Gas
input = []byte{}
initContainer = scope.Contract.Container.SubContainer[initContainerIdx]
)

if inputSize > 0 {
input = scope.Memory.GetCopy(int64(inputOffset), int64(inputSize))
}
// Apply EIP150
gas -= gas / 64
scope.Contract.UseGas(gas)

stackValue := size

res, addr, returnGas, suberr := interpreter.evm.Create3(scope.Contract, input, initContainer, gas, &endowment, &salt)

// Push item on the stack based on the returned error.
if suberr != nil {
stackValue.Clear()
} else {
stackValue.SetBytes(addr.Bytes())
}

scope.Stack.Push(&stackValue)
scope.Contract.Gas += returnGas

if suberr == ErrExecutionReverted {
interpreter.returnData = res // set REVERT data to return data buffer
return res, nil
}
interpreter.returnData = nil // clear dirty return data buffer
return nil, nil
}

func opCreate4(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return nil, nil
}

func opReturnContract(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return nil, nil
}
7 changes: 4 additions & 3 deletions core/vm/eof.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,10 @@ func isEOFVersion1(code []byte) bool {

// Container is an EOF container object.
type Container struct {
Types []*FunctionMetadata
Code [][]byte
Data []byte
Types []*FunctionMetadata
Code [][]byte
SubContainer [][]byte
Data []byte
}

// FunctionMetadata is an EOF function signature.
Expand Down
10 changes: 10 additions & 0 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,16 @@ func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *
return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2, true /* incrementNonce */, isCallerEOF)
}

func (evm *EVM) Create3(caller ContractRef, code, initContainer []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr libcommon.Address, leftOverGas uint64, err error) {
// TODO
return nil, libcommon.Address{}, 0, nil
}

func (evm *EVM) Create4(caller ContractRef, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr libcommon.Address, leftOverGas uint64, err error) {
// TODO
return nil, libcommon.Address{}, 0, nil
}

// SysCreate is a special (system) contract creation methods for genesis constructors.
// Unlike the normal Create & Create2, it doesn't increment caller's nonce.
func (evm *EVM) SysCreate(caller ContractRef, code []byte, gas uint64, endowment *uint256.Int, contractAddr libcommon.Address) (ret []byte, leftOverGas uint64, err error) {
Expand Down
82 changes: 41 additions & 41 deletions core/vm/opcodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,21 +207,21 @@ const (

// 0xe0 range - eof ops.
const (
RJUMP OpCode = 0xe0
RJUMPI OpCode = 0xe1
RJUMPV OpCode = 0xe2
CALLF OpCode = 0xe3
RETF OpCode = 0xe4
JUMPF OpCode = 0xe5
DUPN OpCode = 0xe6
SWAPN OpCode = 0xe7
DATALOAD OpCode = 0xe8
DATALOADN OpCode = 0xe9
DATASIZE OpCode = 0xea
DATACOPY OpCode = 0xeb
// CREATE3 OpCode = 0xec
// CREATE4 OpCode = 0xed
// RETURNCONTRACT OpCode = 0xee
RJUMP OpCode = 0xe0
RJUMPI OpCode = 0xe1
RJUMPV OpCode = 0xe2
CALLF OpCode = 0xe3
RETF OpCode = 0xe4
JUMPF OpCode = 0xe5
DUPN OpCode = 0xe6
SWAPN OpCode = 0xe7
DATALOAD OpCode = 0xe8
DATALOADN OpCode = 0xe9
DATASIZE OpCode = 0xea
DATACOPY OpCode = 0xeb
CREATE3 OpCode = 0xec
CREATE4 OpCode = 0xed
RETURNCONTRACT OpCode = 0xee
)

// 0xf0 range - closures.
Expand Down Expand Up @@ -398,21 +398,21 @@ var opCodeToString = map[OpCode]string{
LOG4: "LOG4",

// 0xe0 range.
RJUMP: "RJUMP",
RJUMPI: "RJUMPI",
RJUMPV: "RJUMPV",
CALLF: "CALLF",
RETF: "RETF",
JUMPF: "JUMPF",
DUPN: "DUPN",
SWAPN: "SWAPN",
DATALOAD: "DATALOAD",
DATALOADN: "DATALOADN",
DATASIZE: "DATASIZE",
DATACOPY: "DATACOPY",
// CREATE3: "CREATE3",
// CREATE4: "CREATE4",
// RETURNCONTRACT: "RETURNCONTRACT",
RJUMP: "RJUMP",
RJUMPI: "RJUMPI",
RJUMPV: "RJUMPV",
CALLF: "CALLF",
RETF: "RETF",
JUMPF: "JUMPF",
DUPN: "DUPN",
SWAPN: "SWAPN",
DATALOAD: "DATALOAD",
DATALOADN: "DATALOADN",
DATASIZE: "DATASIZE",
DATACOPY: "DATACOPY",
CREATE3: "CREATE3",
CREATE4: "CREATE4",
RETURNCONTRACT: "RETURNCONTRACT",

// 0xf0 range.
CREATE: "CREATE",
Expand Down Expand Up @@ -590,17 +590,17 @@ var stringToOp = map[string]OpCode{
"DATALOADN": DATALOADN,
"DATASIZE": DATASIZE,
"DATACOPY": DATACOPY,
// "CREATE3": CREATE3,
// "CREATE4": CREATE4,
// "RETURNCONTRACT": RETURNCONTRACT,
"CREATE": CREATE,
"CREATE2": CREATE2,
"CALL": CALL,
"RETURN": RETURN,
"CALLCODE": CALLCODE,
"REVERT": REVERT,
"INVALID": INVALID,
"SELFDESTRUCT": SELFDESTRUCT,
"CREATE3": CREATE3,
"CREATE4": CREATE4,
"RETURNCONTRACT": RETURNCONTRACT,
"CREATE": CREATE,
"CREATE2": CREATE2,
"CALL": CALL,
"RETURN": RETURN,
"CALLCODE": CALLCODE,
"REVERT": REVERT,
"INVALID": INVALID,
"SELFDESTRUCT": SELFDESTRUCT,
}

// StringToOp finds the opcode whose name is stored in `str`.
Expand Down
2 changes: 2 additions & 0 deletions params/protocol_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ const (
LogTopicGas uint64 = 375 // Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas.
CreateGas uint64 = 32000 // Once per CREATE operation & contract-creation transaction.
Create2Gas uint64 = 32000 // Once per CREATE2 operation
Create3Gas uint64 = 32000 // Once per CREATE3 operation
Create4Gas uint64 = 32000 // Once per CREATE4 operation
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.

Expand Down

0 comments on commit a48e4fe

Please sign in to comment.