From daea23d01d3a94f4ee0af9125e65c86e416b915d Mon Sep 17 00:00:00 2001 From: Petar Ivanov <29689712+dartdart26@users.noreply.github.com> Date: Tue, 6 Dec 2022 11:19:52 +0200 Subject: [PATCH] Create protected storage on the CREATE2 opcode Create the protected storage contract on the CREATE2 opcode. Add the create2.sol example that shows CREATE2 contract creation. Also, show that recreating a contract via CREATE2(including its associated protected storage) works and the address is the same deterministic one. For more information, please see: https://docs.soliditylang.org/en/v0.8.17/control-structures.html?highlight=create2#salted-contract-creations-create2 --- core/vm/evm.go | 18 ++++++++++-- tests/solidity/zama/create2.sol | 50 +++++++++++++++++++++++++++++++++ tests/solidity/zama/handles.sol | 2 +- 3 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 tests/solidity/zama/create2.sol diff --git a/core/vm/evm.go b/core/vm/evm.go index 0e6d5b30d417..4a40a7986603 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -518,9 +518,21 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I // The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:] // instead of the usual sender-and-nonce-hash as the address where the contract is initialized at. func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { - codeAndHash := &codeAndHash{code: code} - contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), codeAndHash.Hash().Bytes()) - return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2) + actualCodeAndHash := &codeAndHash{code: code} + + // Create the actual contract. + contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), actualCodeAndHash.Hash().Bytes()) + + ret, contractAddr, leftOverGas, err = evm.create(caller, actualCodeAndHash, gas, endowment, contractAddr, CREATE2) + if err != nil { + return + } + + // Create a separate contract that would be used for protected storage. + // Return the actual contract's return value and contract address. + protectedStorageContractAddr := crypto.CreateProtectedStorageContractAddress(contractAddr) + _, _, leftOverGas, err = evm.create(caller, &codeAndHash{}, gas, endowment, protectedStorageContractAddr, CREATE2) + return } // ChainConfig returns the environment's chain configuration diff --git a/tests/solidity/zama/create2.sol b/tests/solidity/zama/create2.sol new file mode 100644 index 000000000000..24bcd7c90eb9 --- /dev/null +++ b/tests/solidity/zama/create2.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear + +pragma solidity >=0.7.0 <0.9.0; + +contract Contract { + uint256 public value; + + constructor(uint256 v) { + value = v; + } + + function get() public view returns (uint256) { + return value; + } + + function destruct() public { + selfdestruct(payable(tx.origin)); + } +} + +// Salt: 0x0102abcdef0102abcdef0102abcdef0102abcdef0102abcdef0102abcdefaaaa + +// Creates a member contract via the CREATE2 opcode. +contract Factory { + Contract public c; + bytes32 public original_salt; + uint256 public original_value; + address public original_address; + + constructor(bytes32 salt, uint256 value) { + c = new Contract{salt: salt}(value); + original_salt = salt; + original_value = value; + original_address = address(c); + } + + function get() public view returns (uint256) { + return c.get(); + } + + function destruct() public { + c.destruct(); + } + + // After `destruct()` is called, `recreate()` must succeed and `c` must have the same address as before. + function recreate() public { + c = new Contract{salt: original_salt}(original_value); + require(original_address == address(c)); + } +} diff --git a/tests/solidity/zama/handles.sol b/tests/solidity/zama/handles.sol index 2ebd9b17be3d..e77708819485 100644 --- a/tests/solidity/zama/handles.sol +++ b/tests/solidity/zama/handles.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0 +// SPDX-License-Identifier: BSD-3-Clause-Clear pragma solidity >=0.7.0 <0.9.0;