From 3a2f51648518c9f632e0bff9d2b8a65dc45ed5cb Mon Sep 17 00:00:00 2001 From: Petar Ivanov <29689712+dartdart26@users.noreply.github.com> Date: Mon, 30 Oct 2023 18:00:09 +0200 Subject: [PATCH] feat: implement opCreate and opCreate2 in fhevm-go --- fhevm/evm.go | 28 ++++++++++++++++++++++++++++ fhevm/interface.go | 6 ++++++ 2 files changed, 34 insertions(+) diff --git a/fhevm/evm.go b/fhevm/evm.go index 826b17e..db090e6 100644 --- a/fhevm/evm.go +++ b/fhevm/evm.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/holiman/uint256" + ps "github.com/zama-ai/fhevm-go/crypto" ) // A Logger interface for the EVM. @@ -166,3 +167,30 @@ func padArrayTo32Multiple(input []byte) []byte { } return input } + +func Create(evm EVMEnvironment, caller common.Address, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { + contractAddr = crypto.CreateAddress(caller, evm.GetNonce(caller)) + protectedStorageAddr := ps.CreateProtectedStorageContractAddress(contractAddr) + _, _, leftOverGas, err = evm.CreateContract(caller, nil, gas, big.NewInt(0), protectedStorageAddr) + if err != nil { + ret = nil + contractAddr = common.Address{} + return + } + // TODO: consider reverting changes to `protectedStorageAddr` if actual contract creation fails. + return evm.CreateContract(caller, code, leftOverGas, value, contractAddr) +} + +func Create2(evm EVMEnvironment, caller common.Address, code []byte, gas uint64, endowment *big.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { + codeHash := crypto.Keccak256Hash(code) + contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), codeHash.Bytes()) + protectedStorageAddr := ps.CreateProtectedStorageContractAddress(contractAddr) + _, _, leftOverGas, err = evm.CreateContract2(caller, nil, common.Hash{}, gas, big.NewInt(0), protectedStorageAddr) + if err != nil { + ret = nil + contractAddr = common.Address{} + return + } + // TODO: consider reverting changes to `protectedStorageAddr` if actual contract creation fails. + return evm.CreateContract2(caller, code, codeHash, leftOverGas, endowment, contractAddr) +} diff --git a/fhevm/interface.go b/fhevm/interface.go index 2c9a644..ca3f3b4 100644 --- a/fhevm/interface.go +++ b/fhevm/interface.go @@ -1,6 +1,8 @@ package fhevm import ( + "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" ) @@ -9,6 +11,7 @@ type EVMEnvironment interface { // StateDB related functions GetState(common.Address, common.Hash) common.Hash SetState(common.Address, common.Hash, common.Hash) + GetNonce(common.Address) uint64 // EVM call stack depth GetDepth() int @@ -21,6 +24,9 @@ type EVMEnvironment interface { IsEthCall() bool IsReadOnly() bool + CreateContract(caller common.Address, code []byte, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) + CreateContract2(caller common.Address, code []byte, codeHash common.Hash, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) + GetFhevmData() *FhevmData }