// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Encoding} from "./Encoding.sol"; import {Types} from "./Types.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 ) ); } }