diff --git a/system-contracts/contracts/AccountCodeStorage.sol b/system-contracts/contracts/AccountCodeStorage.sol index 52879df1f..4c726a73b 100644 --- a/system-contracts/contracts/AccountCodeStorage.sol +++ b/system-contracts/contracts/AccountCodeStorage.sol @@ -23,6 +23,9 @@ import {Unauthorized, InvalidCodeHash, CodeHashReason} from "./SystemContractErr contract AccountCodeStorage is IAccountCodeStorage { bytes32 private constant EMPTY_STRING_KECCAK = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; + /// @dev Prefix for EVM contracts hashes storage slots. + uint256 private constant EVM_HASHES_PREFIX = 1 << 254; + modifier onlyDeployer() { if (msg.sender != address(DEPLOYER_SYSTEM_CONTRACT)) { revert Unauthorized(msg.sender); @@ -81,6 +84,16 @@ contract AccountCodeStorage is IAccountCodeStorage { } } + /// @notice Stores the keccak hash of constructed EVM contract. + /// @param _address The address of the account to set the hash to. + /// @param _hash The new keccak hash of the constructed EVM account. + /// @dev This method can be called only by ContractDeployer. + function storeAccountEvmHash(address _address, bytes32 _hash) external override onlyDeployer { + assembly { + sstore(or(EVM_HASHES_PREFIX, _address), _hash) + } + } + /// @notice Get the codehash stored for an address. /// @param _address The address of the account of which the codehash to return /// @return codeHash The codehash stored for this account. @@ -116,7 +129,7 @@ contract AccountCodeStorage is IAccountCodeStorage { else if (Utils.isContractConstructing(codeHash)) { codeHash = EMPTY_STRING_KECCAK; } else if (Utils.isCodeHashEVM(codeHash)) { - codeHash = DEPLOYER_SYSTEM_CONTRACT.evmCodeHash(account); + codeHash = _getEvmCodeHash(account); } return codeHash; @@ -153,4 +166,15 @@ contract AccountCodeStorage is IAccountCodeStorage { bytes32 bytecodeHash = getRawCodeHash(_addr); return Utils.isCodeHashEVM(bytecodeHash); } + + /// @notice Returns keccak of EVM bytecode at address if it is an EVM contract. Returns bytes32(0) if it isn't a EVM contract. + function getEvmCodeHash(address _address) external view override returns (bytes32 _hash) { + _hash = _getEvmCodeHash(_address); + } + + function _getEvmCodeHash(address _address) internal view returns (bytes32 _hash) { + assembly { + _hash := sload(or(EVM_HASHES_PREFIX, _address)) + } + } } diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 3b36ed732..f2905d8f9 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -22,8 +22,6 @@ import {Unauthorized, InvalidAllowedBytecodeTypesMode, InvalidNonceOrderingChang * do not need to be published anymore. */ contract ContractDeployer is IContractDeployer, SystemContractBase { - /// @dev Prefix for EVM contracts hashes storage slots. - uint256 private constant EVM_HASHES_PREFIX = 1 << 254; /// @dev keccak256("ALLOWED_BYTECODE_TYPES_MODE_SLOT"). bytes32 private constant ALLOWED_BYTECODE_TYPES_MODE_SLOT = 0xd70708d0b933e26eab552567ce3a8ad69e6fbec9a2a68f16d51bd417a47d9d3b; @@ -44,11 +42,6 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { mode = _getAllowedBytecodeTypesMode(); } - /// @notice Returns keccak of EVM bytecode at address if it is an EVM contract. Returns bytes32(0) if it isn't a EVM contract. - function evmCodeHash(address _address) external view returns (bytes32 _hash) { - _hash = _getEvmCodeHash(_address); - } - /// @notice Returns information about a certain account. function getAccountInfo(address _address) external view returns (AccountInfo memory info) { return accountInfo[_address]; @@ -250,7 +243,12 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { address _newAddress, bytes calldata _initCode ) external payable onlySystemCallFromEvmEmulator returns (uint256, address) { - uint256 constructorReturnEvmGas = _performDeployOnAddressEVM(msg.sender, _newAddress, AccountAbstractionVersion.None, _initCode); + uint256 constructorReturnEvmGas = _performDeployOnAddressEVM( + msg.sender, + _newAddress, + AccountAbstractionVersion.None, + _initCode + ); return (constructorReturnEvmGas, _newAddress); } @@ -607,23 +605,11 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { evmBytecodeHash := keccak256(add(paddedBytecode, 0x40), bytecodeLen) } - _setEvmCodeHash(_newAddress, evmBytecodeHash); + ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.storeAccountEvmHash(_newAddress, evmBytecodeHash); emit ContractDeployed(_sender, versionedCodeHash, _newAddress); } - function _setEvmCodeHash(address _address, bytes32 _hash) internal { - assembly { - sstore(or(EVM_HASHES_PREFIX, _address), _hash) - } - } - - function _getEvmCodeHash(address _address) internal view returns (bytes32 _hash) { - assembly { - _hash := sload(or(EVM_HASHES_PREFIX, _address)) - } - } - function _getAllowedBytecodeTypesMode() internal view returns (AllowedBytecodeTypes mode) { assembly { mode := sload(ALLOWED_BYTECODE_TYPES_MODE_SLOT) diff --git a/system-contracts/contracts/interfaces/IAccountCodeStorage.sol b/system-contracts/contracts/interfaces/IAccountCodeStorage.sol index 7bd24cc75..8cca24fb5 100644 --- a/system-contracts/contracts/interfaces/IAccountCodeStorage.sol +++ b/system-contracts/contracts/interfaces/IAccountCodeStorage.sol @@ -9,11 +9,15 @@ interface IAccountCodeStorage { function markAccountCodeHashAsConstructed(address _address) external; + function storeAccountEvmHash(address _address, bytes32 _hash) external; + function getRawCodeHash(address _address) external view returns (bytes32 codeHash); function getCodeHash(uint256 _input) external view returns (bytes32 codeHash); function getCodeSize(uint256 _input) external view returns (uint256 codeSize); + function getEvmCodeHash(address) external view returns (bytes32); + function isAccountEVM(address _addr) external view returns (bool); } diff --git a/system-contracts/contracts/interfaces/IContractDeployer.sol b/system-contracts/contracts/interfaces/IContractDeployer.sol index 83bf2392e..ae90bfee3 100644 --- a/system-contracts/contracts/interfaces/IContractDeployer.sol +++ b/system-contracts/contracts/interfaces/IContractDeployer.sol @@ -109,9 +109,6 @@ interface IContractDeployer { bytes calldata _initCode ) external payable returns (uint256 evmGasUsed, address newAddress); - /// @notice Returns keccak of EVM bytecode at address if it is an EVM contract. Returns bytes32(0) if it isn't a EVM contract. - function evmCodeHash(address) external view returns (bytes32); - /// @notice Changes what types of bytecodes are allowed to be deployed on the chain. Can be used only during upgrades. /// @param newAllowedBytecodeTypes The new allowed bytecode types mode. function setAllowedBytecodeTypesToDeploy(uint256 newAllowedBytecodeTypes) external;