// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { Types } from "./Types.sol"; import { Encoding } from "./Encoding.sol"; /** * @title Hashing * @notice Hashing handles Optimism's various different hashing schemes. */ library Hashing { /** * @notice Computes the hash of the RLP encoded L2 transaction that would be generated when a * given deposit is sent to the L2 system. Useful for searching for a deposit in the L2 * system. * * @param _tx User deposit transaction to hash. * * @return Hash of the RLP encoded L2 deposit transaction. */ function hashDepositTransaction(Types.UserDepositTransaction memory _tx) internal pure returns (bytes32) { return keccak256(Encoding.encodeDepositTransaction(_tx)); } /** * @notice Computes the deposit transaction's "source hash", a value that guarantees the hash * of the L2 transaction that corresponds to a deposit is unique and is * deterministically generated from L1 transaction data. * * @param _l1BlockHash Hash of the L1 block where the deposit was included. * @param _logIndex The index of the log that created the deposit transaction. * * @return Hash of the deposit transaction's "source hash". */ function hashDepositSource(bytes32 _l1BlockHash, uint256 _logIndex) internal pure returns (bytes32) { bytes32 depositId = keccak256(abi.encode(_l1BlockHash, _logIndex)); return keccak256(abi.encode(bytes32(0), depositId)); } /** * @notice Hashes the cross domain message based on the version that is encoded into the * message nonce. * * @param _nonce Message nonce with version encoded into the first two bytes. * @param _sender Address of the sender of the message. * @param _target Address of the target of the message. * @param _value ETH value to send to the target. * @param _gasLimit Gas limit to use for the message. * @param _data Data to send with the message. * * @return Hashed cross domain message. */ function hashCrossDomainMessage( uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes memory _data ) internal pure returns (bytes32) { (, uint16 version) = Encoding.decodeVersionedNonce(_nonce); if (version == 0) { return hashCrossDomainMessageV0(_target, _sender, _data, _nonce); } else if (version == 1) { return hashCrossDomainMessageV1(_nonce, _sender, _target, _value, _gasLimit, _data); } else { revert("Hashing: unknown cross domain message version"); } } /** * @notice Hashes a cross domain message based on the V0 (legacy) encoding. * * @param _target Address of the target of the message. * @param _sender Address of the sender of the message. * @param _data Data to send with the message. * @param _nonce Message nonce. * * @return Hashed cross domain message. */ function hashCrossDomainMessageV0( address _target, address _sender, bytes memory _data, uint256 _nonce ) internal pure returns (bytes32) { return keccak256(Encoding.encodeCrossDomainMessageV0(_target, _sender, _data, _nonce)); } /** * @notice Hashes a cross domain message based on the V1 (current) encoding. * * @param _nonce Message nonce. * @param _sender Address of the sender of the message. * @param _target Address of the target of the message. * @param _value ETH value to send to the target. * @param _gasLimit Gas limit to use for the message. * @param _data Data to send with the message. * * @return Hashed cross domain message. */ function hashCrossDomainMessageV1( uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes memory _data ) internal pure returns (bytes32) { return keccak256( Encoding.encodeCrossDomainMessageV1( _nonce, _sender, _target, _value, _gasLimit, _data ) ); } /** * @notice Derives the withdrawal hash according to the encoding in the L2 Withdrawer contract * * @param _tx Withdrawal transaction to hash. * * @return Hashed withdrawal transaction. */ function hashWithdrawal(Types.WithdrawalTransaction memory _tx) internal pure returns (bytes32) { return keccak256( abi.encode(_tx.nonce, _tx.sender, _tx.target, _tx.value, _tx.gasLimit, _tx.data) ); } /** * @notice Hashes the various elements of an output root proof into an output root hash which * can be used to check if the proof is valid. * * @param _outputRootProof Output root proof which should hash to an output root. * * @return Hashed output root proof. */ function hashOutputRootProof(Types.OutputRootProof memory _outputRootProof) internal pure returns (bytes32) { return keccak256( abi.encode( _outputRootProof.version, _outputRootProof.stateRoot, _outputRootProof.messagePasserStorageRoot, _outputRootProof.latestBlockhash ) ); } }