Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(EVM): Move EVM hashes to account code storage #1144

Draft
wants to merge 1 commit into
base: evm-emulator/fixes
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion system-contracts/contracts/AccountCodeStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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))
}
}
}
28 changes: 7 additions & 21 deletions system-contracts/contracts/ContractDeployer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
* 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;
Expand All @@ -44,11 +42,6 @@
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];
Expand Down Expand Up @@ -181,7 +174,7 @@
function createEVM(bytes calldata _initCode) external payable override onlySystemCall returns (uint256, address) {
uint256 senderNonce;
// If the account is an EOA, use the min nonce. If it's a contract, use deployment nonce
if (msg.sender == tx.origin) {

Check warning on line 177 in system-contracts/contracts/ContractDeployer.sol

View workflow job for this annotation

GitHub Actions / lint

Avoid to use tx.origin

Check warning on line 177 in system-contracts/contracts/ContractDeployer.sol

View workflow job for this annotation

GitHub Actions / lint

Avoid to use tx.origin

Check warning on line 177 in system-contracts/contracts/ContractDeployer.sol

View workflow job for this annotation

GitHub Actions / lint

Avoid to use tx.origin
// Subtract 1 for EOA since the nonce has already been incremented for this transaction
senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.getMinNonce(msg.sender) - 1;
} else {
Expand Down Expand Up @@ -250,7 +243,12 @@
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);
}

Expand Down Expand Up @@ -607,23 +605,11 @@
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
3 changes: 0 additions & 3 deletions system-contracts/contracts/interfaces/IContractDeployer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading