From 973539b022f47a57a9342d36e6a39fd3f04569d2 Mon Sep 17 00:00:00 2001 From: Petar Ivanov <29689712+dartdart26@users.noreply.github.com> Date: Thu, 2 Nov 2023 18:11:27 +0200 Subject: [PATCH] feat: add implementation of OpSelfdestruct --- fhevm/evm.go | 6 +++--- fhevm/instructions.go | 18 +++++++++++++++--- fhevm/interface.go | 4 ++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/fhevm/evm.go b/fhevm/evm.go index db090e6..e986d12 100644 --- a/fhevm/evm.go +++ b/fhevm/evm.go @@ -9,7 +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" + fhevm_crypto "github.com/zama-ai/fhevm-go/crypto" ) // A Logger interface for the EVM. @@ -170,7 +170,7 @@ func padArrayTo32Multiple(input []byte) []byte { 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) + protectedStorageAddr := fhevm_crypto.CreateProtectedStorageContractAddress(contractAddr) _, _, leftOverGas, err = evm.CreateContract(caller, nil, gas, big.NewInt(0), protectedStorageAddr) if err != nil { ret = nil @@ -184,7 +184,7 @@ func Create(evm EVMEnvironment, caller common.Address, code []byte, gas uint64, 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) + protectedStorageAddr := fhevm_crypto.CreateProtectedStorageContractAddress(contractAddr) _, _, leftOverGas, err = evm.CreateContract2(caller, nil, common.Hash{}, gas, big.NewInt(0), protectedStorageAddr) if err != nil { ret = nil diff --git a/fhevm/instructions.go b/fhevm/instructions.go index 87237bd..3f479e3 100644 --- a/fhevm/instructions.go +++ b/fhevm/instructions.go @@ -4,12 +4,13 @@ import ( "bytes" "encoding/hex" "errors" + "math/big" "strings" "github.com/ethereum/go-ethereum/common" crypto "github.com/ethereum/go-ethereum/crypto" "github.com/holiman/uint256" - ps "github.com/zama-ai/fhevm-go/crypto" + fhevm_crypto "github.com/zama-ai/fhevm-go/crypto" ) var zero = uint256.NewInt(0).Bytes32() @@ -152,7 +153,7 @@ func verifyIfCiphertextHandle(handle common.Hash, env EVMEnvironment, contractAd } metadataKey := crypto.Keccak256Hash(handle.Bytes()) - protectedStorage := ps.CreateProtectedStorageContractAddress(contractAddress) + protectedStorage := fhevm_crypto.CreateProtectedStorageContractAddress(contractAddress) metadataInt := newInt(env.GetState(protectedStorage, metadataKey).Bytes()) if !metadataInt.IsZero() { metadata := newCiphertextMetadata(metadataInt.Bytes32()) @@ -274,7 +275,7 @@ func OpSstore(pc *uint64, env EVMEnvironment, scope ScopeContext) ([]byte, error oldValHash := env.GetState(scope.GetContract().Address(), common.Hash(loc.Bytes32())) // If the value is the same or if we are not going to commit, don't do anything to protected storage. if newValHash != oldValHash && env.IsCommitting() { - protectedStorage := ps.CreateProtectedStorageContractAddress(scope.GetContract().Address()) + protectedStorage := fhevm_crypto.CreateProtectedStorageContractAddress(scope.GetContract().Address()) // Define flag location as keccak256(keccak256(loc)) in protected storage. Used to mark the location as containing a handle. // Note: We apply the hash function twice to make sure a flag location in protected storage cannot clash with a ciphertext @@ -352,3 +353,14 @@ func OpReturn(pc *uint64, env EVMEnvironment, scope ScopeContext) []byte { delegateCiphertextHandlesToCaller(env, ret) return ret } + +func OpSelfdestruct(pc *uint64, env EVMEnvironment, scope ScopeContext) (beneficiary uint256.Int, balance *big.Int) { + beneficiary = scope.GetStack().Pop() + protectedStorage := fhevm_crypto.CreateProtectedStorageContractAddress(scope.GetContract().Address()) + balance = env.GetBalance(scope.GetContract().Address()) + balance.Add(balance, env.GetBalance(protectedStorage)) + env.AddBalance(beneficiary.Bytes20(), balance) + env.Suicide(scope.GetContract().Address()) + env.Suicide(protectedStorage) + return +} diff --git a/fhevm/interface.go b/fhevm/interface.go index ca3f3b4..75c8285 100644 --- a/fhevm/interface.go +++ b/fhevm/interface.go @@ -12,6 +12,10 @@ type EVMEnvironment interface { GetState(common.Address, common.Hash) common.Hash SetState(common.Address, common.Hash, common.Hash) GetNonce(common.Address) uint64 + AddBalance(common.Address, *big.Int) + GetBalance(common.Address) *big.Int + + Suicide(common.Address) bool // EVM call stack depth GetDepth() int