{
  "language": "Solidity",
  "sources": {
    "@layerzerolabs/solidity-examples/contracts/lzApp/interfaces/ILayerZeroEndpoint.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n    // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n    // @param _dstChainId - the destination chain identifier\n    // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n    // @param _payload - a custom bytes payload to send to the destination contract\n    // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n    // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n    // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n    function send(\n        uint16 _dstChainId,\n        bytes calldata _destination,\n        bytes calldata _payload,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes calldata _adapterParams\n    ) external payable;\n\n    // @notice used by the messaging library to publish verified payload\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source contract (as bytes) at the source chain\n    // @param _dstAddress - the address on destination chain\n    // @param _nonce - the unbound message ordering nonce\n    // @param _gasLimit - the gas limit for external contract execution\n    // @param _payload - verified payload to send to the destination contract\n    function receivePayload(\n        uint16 _srcChainId,\n        bytes calldata _srcAddress,\n        address _dstAddress,\n        uint64 _nonce,\n        uint _gasLimit,\n        bytes calldata _payload\n    ) external;\n\n    // @notice get the inboundNonce of a lzApp from a source chain which could be EVM or non-EVM chain\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source chain contract address\n    function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n    // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n    // @param _srcAddress - the source chain contract address\n    function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n    // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n    // @param _dstChainId - the destination chain identifier\n    // @param _userApplication - the user app address on this EVM chain\n    // @param _payload - the custom message to send over LayerZero\n    // @param _payInZRO - if false, user app pays the protocol fee in native token\n    // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n    function estimateFees(\n        uint16 _dstChainId,\n        address _userApplication,\n        bytes calldata _payload,\n        bool _payInZRO,\n        bytes calldata _adapterParam\n    ) external view returns (uint nativeFee, uint zroFee);\n\n    // @notice get this Endpoint's immutable source identifier\n    function getChainId() external view returns (uint16);\n\n    // @notice the interface to retry failed message on this Endpoint destination\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source chain contract address\n    // @param _payload - the payload to be retried\n    function retryPayload(\n        uint16 _srcChainId,\n        bytes calldata _srcAddress,\n        bytes calldata _payload\n    ) external;\n\n    // @notice query if any STORED payload (message blocking) at the endpoint.\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source chain contract address\n    function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n    // @notice query if the _libraryAddress is valid for sending msgs.\n    // @param _userApplication - the user app address on this EVM chain\n    function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n    // @notice query if the _libraryAddress is valid for receiving msgs.\n    // @param _userApplication - the user app address on this EVM chain\n    function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n    // @notice query if the non-reentrancy guard for send() is on\n    // @return true if the guard is on. false otherwise\n    function isSendingPayload() external view returns (bool);\n\n    // @notice query if the non-reentrancy guard for receive() is on\n    // @return true if the guard is on. false otherwise\n    function isReceivingPayload() external view returns (bool);\n\n    // @notice get the configuration of the LayerZero messaging library of the specified version\n    // @param _version - messaging library version\n    // @param _chainId - the chainId for the pending config change\n    // @param _userApplication - the contract address of the user application\n    // @param _configType - type of configuration. every messaging library has its own convention.\n    function getConfig(\n        uint16 _version,\n        uint16 _chainId,\n        address _userApplication,\n        uint _configType\n    ) external view returns (bytes memory);\n\n    // @notice get the send() LayerZero messaging library version\n    // @param _userApplication - the contract address of the user application\n    function getSendVersion(address _userApplication) external view returns (uint16);\n\n    // @notice get the lzReceive() LayerZero messaging library version\n    // @param _userApplication - the contract address of the user application\n    function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n"
    },
    "@layerzerolabs/solidity-examples/contracts/lzApp/interfaces/ILayerZeroUserApplicationConfig.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n    // @notice set the configuration of the LayerZero messaging library of the specified version\n    // @param _version - messaging library version\n    // @param _chainId - the chainId for the pending config change\n    // @param _configType - type of configuration. every messaging library has its own convention.\n    // @param _config - configuration in the bytes. can encode arbitrary content.\n    function setConfig(\n        uint16 _version,\n        uint16 _chainId,\n        uint _configType,\n        bytes calldata _config\n    ) external;\n\n    // @notice set the send() LayerZero messaging library version to _version\n    // @param _version - new messaging library version\n    function setSendVersion(uint16 _version) external;\n\n    // @notice set the lzReceive() LayerZero messaging library version to _version\n    // @param _version - new messaging library version\n    function setReceiveVersion(uint16 _version) external;\n\n    // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n    // @param _srcChainId - the chainId of the source chain\n    // @param _srcAddress - the contract address of the source contract at the source chain\n    function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n"
    },
    "@openzeppelin/contracts/access/IAccessControl.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted signaling this.\n     *\n     * _Available since v3.1._\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call, an admin role\n     * bearer except when using {AccessControl-_setupRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(bytes32 role, address account) external;\n}\n"
    },
    "@openzeppelin/contracts/access/Ownable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
    },
    "@openzeppelin/contracts/security/Pausable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    bool private _paused;\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    constructor() {\n        _paused = false;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        require(!paused(), \"Pausable: paused\");\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        require(paused(), \"Pausable: not paused\");\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"
    },
    "@openzeppelin/contracts/security/ReentrancyGuard.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    constructor() {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/Context.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
    },
    "@venusprotocol/solidity-utilities/contracts/validators.sol": {
      "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\nerror ZeroAddressNotAllowed();\n\n/// @notice Thrown if the supplied value is 0 where it is not allowed\nerror ZeroValueNotAllowed();\n\n/// @notice Checks if the provided address is nonzero, reverts otherwise\n/// @param address_ Address to check\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\nfunction ensureNonzeroAddress(address address_) pure {\n    if (address_ == address(0)) {\n        revert ZeroAddressNotAllowed();\n    }\n}\n\n/// @notice Checks if the provided value is nonzero, reverts otherwise\n/// @param value_ Value to check\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\nfunction ensureNonzeroValue(uint256 value_) pure {\n    if (value_ == 0) {\n        revert ZeroValueNotAllowed();\n    }\n}\n"
    },
    "contracts/Cross-chain/BaseOmnichainControllerSrc.sol": {
      "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { Pausable } from \"@openzeppelin/contracts/security/Pausable.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { IAccessControlManagerV8 } from \"./../Governance/IAccessControlManagerV8.sol\";\n\n/**\n * @title BaseOmnichainControllerSrc\n * @dev This contract is the base for the Omnichain controller source contracts.\n * It provides functionality related to daily command limits and pausability.\n * @custom:security-contact https://github.com/VenusProtocol/governance-contracts#discussion\n */\n\ncontract BaseOmnichainControllerSrc is Ownable, Pausable {\n    /**\n     * @notice ACM (Access Control Manager) contract address\n     */\n    address public accessControlManager;\n\n    /**\n     * @notice Maximum daily limit for commands from the local chain\n     */\n    mapping(uint16 => uint256) public chainIdToMaxDailyLimit;\n\n    /**\n     * @notice Total commands transferred within the last 24-hour window from the local chain\n     */\n    mapping(uint16 => uint256) public chainIdToLast24HourCommandsSent;\n\n    /**\n     * @notice Timestamp when the last 24-hour window started from the local chain\n     */\n    mapping(uint16 => uint256) public chainIdToLast24HourWindowStart;\n    /**\n     * @notice Timestamp when the last proposal sent from the local chain to dest chain\n     */\n    mapping(uint16 => uint256) public chainIdToLastProposalSentTimestamp;\n\n    /**\n     * @notice Emitted when the maximum daily limit of commands from the local chain is modified\n     */\n    event SetMaxDailyLimit(uint16 indexed chainId, uint256 oldMaxLimit, uint256 newMaxLimit);\n    /*\n     * @notice Emitted when the address of ACM is updated\n     */\n    event NewAccessControlManager(address indexed oldAccessControlManager, address indexed newAccessControlManager);\n\n    constructor(address accessControlManager_) {\n        ensureNonzeroAddress(accessControlManager_);\n        accessControlManager = accessControlManager_;\n    }\n\n    /**\n     * @notice Sets the limit of daily (24 Hour) command amount\n     * @param chainId_ Destination chain id\n     * @param limit_ Number of commands\n     * @custom:access Controlled by AccessControlManager\n     * @custom:event Emits SetMaxDailyLimit with old and new limit and its corresponding chain id\n     */\n    function setMaxDailyLimit(uint16 chainId_, uint256 limit_) external {\n        // _ensureAllowed(\"setMaxDailyLimit(uint16,uint256)\");\n        emit SetMaxDailyLimit(chainId_, chainIdToMaxDailyLimit[chainId_], limit_);\n        chainIdToMaxDailyLimit[chainId_] = limit_;\n    }\n\n    /**\n     * @notice Triggers the paused state of the controller\n     * @custom:access Controlled by AccessControlManager\n     */\n    function pause() external {\n        // _ensureAllowed(\"pause()\");\n        _pause();\n    }\n\n    /**\n     * @notice Triggers the resume state of the controller\n     * @custom:access Controlled by AccessControlManager\n     */\n    function unpause() external {\n        // _ensureAllowed(\"unpause()\");\n        _unpause();\n    }\n\n    /**\n     * @notice Sets the address of Access Control Manager (ACM)\n     * @param accessControlManager_ The new address of the Access Control Manager\n     * @custom:access Only owner\n     * @custom:event Emits NewAccessControlManager with old and new access control manager addresses\n     */\n    function setAccessControlManager(address accessControlManager_) external onlyOwner {\n        ensureNonzeroAddress(accessControlManager_);\n        emit NewAccessControlManager(accessControlManager, accessControlManager_);\n        accessControlManager = accessControlManager_;\n    }\n\n    /**\n     * @notice Empty implementation of renounce ownership to avoid any mishap\n     */\n    function renounceOwnership() public override {}\n\n    /**\n     * @notice Check eligibility to send commands\n     * @param dstChainId_ Destination chain id\n     * @param noOfCommands_ Number of commands to send\n     */\n    function _isEligibleToSend(uint16 dstChainId_, uint256 noOfCommands_) internal {\n        // Load values for the 24-hour window checks\n        uint256 currentBlockTimestamp = block.timestamp;\n        uint256 lastDayWindowStart = chainIdToLast24HourWindowStart[dstChainId_];\n        uint256 commandsSentInWindow = chainIdToLast24HourCommandsSent[dstChainId_];\n        uint256 maxDailyLimit = chainIdToMaxDailyLimit[dstChainId_];\n        uint256 lastProposalSentTimestamp = chainIdToLastProposalSentTimestamp[dstChainId_];\n\n        // Check if the time window has changed (more than 24 hours have passed)\n        if (currentBlockTimestamp - lastDayWindowStart > 1 days) {\n            commandsSentInWindow = noOfCommands_;\n            chainIdToLast24HourWindowStart[dstChainId_] = currentBlockTimestamp;\n        } else {\n            commandsSentInWindow += noOfCommands_;\n        }\n\n        // Revert if the amount exceeds the daily limit\n        require(commandsSentInWindow <= maxDailyLimit, \"Daily Transaction Limit Exceeded\");\n        // Revert if the last proposal is already sent in current block i.e multiple proposals cannot be sent within the same block.timestamp\n        require(lastProposalSentTimestamp != currentBlockTimestamp, \"Multiple bridging in a proposal\");\n\n        // Update the amount for the 24-hour window\n        chainIdToLast24HourCommandsSent[dstChainId_] = commandsSentInWindow;\n        // Update the last sent proposal timestamp\n        chainIdToLastProposalSentTimestamp[dstChainId_] = currentBlockTimestamp;\n    }\n\n    // /**\n    //  * @notice Ensure that the caller has permission to execute a specific function\n    //  * @param functionSig_ Function signature to be checked for permission\n    //  */\n    // function _ensureAllowed(string memory functionSig_) internal view {\n    //     require(\n    //         IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig_),\n    //         \"access denied\"\n    //     );\n    // }\n}\n"
    },
    "contracts/Cross-chain/OmnichainProposalSender.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.25;\n\nimport { ReentrancyGuard } from \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport { ILayerZeroEndpoint } from \"@layerzerolabs/solidity-examples/contracts/lzApp/interfaces/ILayerZeroEndpoint.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { BaseOmnichainControllerSrc } from \"./BaseOmnichainControllerSrc.sol\";\n\n/**\n * @title OmnichainProposalSender\n * @author Venus\n * @notice OmnichainProposalSender contract builds upon the functionality of its parent contract , BaseOmnichainControllerSrc\n * It sends a proposal's data to remote chains for execution after the proposal passes on the main chain\n * when used with GovernorBravo, the owner of this contract must be set to the Timelock contract\n * @custom:security-contact https://github.com/VenusProtocol/governance-contracts#discussion\n */\n\ncontract OmnichainProposalSender is ReentrancyGuard, BaseOmnichainControllerSrc {\n    /**\n     * @notice Stores the total number of remote proposals\n     */\n    uint256 public proposalCount;\n\n    /**\n     * @notice Execution hashes of failed messages\n     * @dev [proposalId] -> [executionHash]\n     */\n    mapping(uint256 => bytes32) public storedExecutionHashes;\n\n    /**\n     * @notice LayerZero endpoint for sending messages to remote chains\n     */\n    ILayerZeroEndpoint public immutable LZ_ENDPOINT;\n\n    /**\n     * @notice Specifies the allowed path for sending messages (remote chainId => remote app address + local app address)\n     */\n    mapping(uint16 => bytes) public trustedRemoteLookup;\n\n    /**\n     * @notice Emitted when a remote message receiver is set for the remote chain\n     */\n    event SetTrustedRemoteAddress(uint16 indexed remoteChainId, bytes oldRemoteAddress, bytes newRemoteAddress);\n\n    /**\n     * @notice Event emitted when trusted remote sets to empty\n     */\n    event TrustedRemoteRemoved(uint16 indexed chainId);\n\n    /**\n     * @notice Emitted when a proposal execution request is sent to the remote chain\n     */\n    event ExecuteRemoteProposal(uint16 indexed remoteChainId, uint256 proposalId, bytes payload);\n\n    /**\n     * @notice Emitted when a previously failed message is successfully sent to the remote chain\n     */\n    event ClearPayload(uint256 indexed proposalId, bytes32 executionHash);\n\n    /**\n     * @notice Emitted when an execution hash of a failed message is saved\n     */\n    event StorePayload(\n        uint256 indexed proposalId,\n        uint16 indexed remoteChainId,\n        bytes payload,\n        bytes adapterParams,\n        uint256 value,\n        bytes reason\n    );\n    /**\n     * @notice Emitted while fallback withdraw\n     */\n    event FallbackWithdraw(address indexed receiver, uint256 value);\n\n    constructor(\n        ILayerZeroEndpoint lzEndpoint_,\n        address accessControlManager_\n    ) BaseOmnichainControllerSrc(accessControlManager_) {\n        ensureNonzeroAddress(address(lzEndpoint_));\n        LZ_ENDPOINT = lzEndpoint_;\n    }\n\n    /**\n     * @notice Estimates LayerZero fees for cross-chain message delivery to the remote chain\n     * @dev The estimated fees are the minimum required; it's recommended to increase the fees amount when sending a message. The unused amount will be refunded\n     * @param remoteChainId_ The LayerZero id of a remote chain\n     * @param payload_ The payload to be sent to the remote chain. It's computed as follows:\n     * payload = abi.encode(abi.encode(targets, values, signatures, calldatas, proposalType), pId)\n     * @param useZro_ Bool that indicates whether to pay in ZRO tokens or not\n     * @param adapterParams_ The params used to specify the custom amount of gas required for the execution on the destination\n     * @return nativeFee The amount of fee in the native gas token (e.g. ETH)\n     * @return zroFee The amount of fee in ZRO token\n     */\n    function estimateFees(\n        uint16 remoteChainId_,\n        bytes calldata payload_,\n        bool useZro_,\n        bytes calldata adapterParams_\n    ) external view returns (uint256, uint256) {\n        return LZ_ENDPOINT.estimateFees(remoteChainId_, address(this), payload_, useZro_, adapterParams_);\n    }\n\n    /**\n     * @notice Remove trusted remote from storage\n     * @param remoteChainId_ The chain's id corresponds to setting the trusted remote to empty\n     * @custom:access Controlled by Access Control Manager\n     * @custom:event Emit TrustedRemoteRemoved with remote chain id\n     */\n    function removeTrustedRemote(uint16 remoteChainId_) external {\n        // _ensureAllowed(\"removeTrustedRemote(uint16)\");\n        require(trustedRemoteLookup[remoteChainId_].length != 0, \"OmnichainProposalSender: trusted remote not found\");\n        delete trustedRemoteLookup[remoteChainId_];\n        emit TrustedRemoteRemoved(remoteChainId_);\n    }\n\n    /**\n     * @notice Sends a message to execute a remote proposal\n     * @dev Stores the hash of the execution parameters if sending fails (e.g., due to insufficient fees)\n     * @param remoteChainId_ The LayerZero id of the remote chain\n     * @param payload_ The payload to be sent to the remote chain\n     * It's computed as follows: payload = abi.encode(targets, values, signatures, calldatas, proposalType)\n     * @param adapterParams_ The params used to specify the custom amount of gas required for the execution on the destination\n     * @param zroPaymentAddress_ The address of the ZRO token holder who would pay for the transaction. This must be either address(this) or tx.origin\n     * @custom:event Emits ExecuteRemoteProposal with remote chain id, proposal ID and payload on success\n     * @custom:event Emits StorePayload with last stored payload proposal ID ,remote chain id , payload, adapter params , values and reason for failure\n     * @custom:access Controlled by Access Control Manager\n     */\n    function execute(\n        uint16 remoteChainId_,\n        bytes calldata payload_,\n        bytes calldata adapterParams_,\n        address zroPaymentAddress_\n    ) external payable whenNotPaused {\n        // _ensureAllowed(\"execute(uint16,bytes,bytes,address)\");\n\n        // A zero value will result in a failed message; therefore, a positive value is required to send a message across the chain.\n        require(msg.value > 0, \"OmnichainProposalSender: value cannot be zero\");\n        require(payload_.length != 0, \"OmnichainProposalSender: empty payload\");\n\n        bytes memory trustedRemote = trustedRemoteLookup[remoteChainId_];\n        require(trustedRemote.length != 0, \"OmnichainProposalSender: destination chain is not a trusted source\");\n        _validateProposal(remoteChainId_, payload_);\n        uint256 _pId = ++proposalCount;\n        bytes memory payload = abi.encode(payload_, _pId);\n\n        try\n            LZ_ENDPOINT.send{ value: msg.value }(\n                remoteChainId_,\n                trustedRemote,\n                payload,\n                payable(msg.sender),\n                zroPaymentAddress_,\n                adapterParams_\n            )\n        {\n            emit ExecuteRemoteProposal(remoteChainId_, _pId, payload);\n        } catch (bytes memory reason) {\n            storedExecutionHashes[_pId] = keccak256(abi.encode(remoteChainId_, payload, adapterParams_, msg.value));\n            emit StorePayload(_pId, remoteChainId_, payload, adapterParams_, msg.value, reason);\n        }\n    }\n\n    /**\n     * @notice Resends a previously failed message\n     * @dev Allows providing more fees if needed. The extra fees will be refunded to the caller\n     * @param pId_ The proposal ID to identify a failed message\n     * @param remoteChainId_ The LayerZero id of the remote chain\n     * @param payload_ The payload to be sent to the remote chain\n     * It's computed as follows: payload = abi.encode(abi.encode(targets, values, signatures, calldatas, proposalType), pId)\n     * @param adapterParams_ The params used to specify the custom amount of gas required for the execution on the destination\n     * @param zroPaymentAddress_ The address of the ZRO token holder who would pay for the transaction.\n     * @param originalValue_ The msg.value passed when execute() function was called\n     * @custom:event Emits ClearPayload with proposal ID and hash\n     * @custom:access Controlled by Access Control Manager\n     */\n    function retryExecute(\n        uint256 pId_,\n        uint16 remoteChainId_,\n        bytes calldata payload_,\n        bytes calldata adapterParams_,\n        address zroPaymentAddress_,\n        uint256 originalValue_\n    ) external payable whenNotPaused nonReentrant {\n        // _ensureAllowed(\"retryExecute(uint256,uint16,bytes,bytes,address,uint256)\");\n        bytes memory trustedRemote = trustedRemoteLookup[remoteChainId_];\n        require(trustedRemote.length != 0, \"OmnichainProposalSender: destination chain is not a trusted source\");\n        bytes32 hash = storedExecutionHashes[pId_];\n        require(hash != bytes32(0), \"OmnichainProposalSender: no stored payload\");\n        require(payload_.length != 0, \"OmnichainProposalSender: empty payload\");\n        (bytes memory payload, ) = abi.decode(payload_, (bytes, uint256));\n        _validateProposal(remoteChainId_, payload);\n\n        require(\n            keccak256(abi.encode(remoteChainId_, payload_, adapterParams_, originalValue_)) == hash,\n            \"OmnichainProposalSender: invalid execution params\"\n        );\n\n        delete storedExecutionHashes[pId_];\n\n        emit ClearPayload(pId_, hash);\n\n        LZ_ENDPOINT.send{ value: originalValue_ + msg.value }(\n            remoteChainId_,\n            trustedRemote,\n            payload_,\n            payable(msg.sender),\n            zroPaymentAddress_,\n            adapterParams_\n        );\n    }\n\n    /**\n     * @notice Clear previously failed message\n     * @param to_ Address of the receiver\n     * @param pId_ The proposal ID to identify a failed message\n     * @param remoteChainId_ The LayerZero id of the remote chain\n     * @param payload_ The payload to be sent to the remote chain\n     * It's computed as follows: payload = abi.encode(abi.encode(targets, values, signatures, calldatas, proposalType), pId)\n     * @param adapterParams_ The params used to specify the custom amount of gas required for the execution on the destination\n     * @param originalValue_ The msg.value passed when execute() function was called\n     * @custom:access Only owner\n     * @custom:event Emits ClearPayload with proposal ID and hash\n     * @custom:event Emits FallbackWithdraw with receiver and amount\n     */\n    function fallbackWithdraw(\n        address to_,\n        uint256 pId_,\n        uint16 remoteChainId_,\n        bytes calldata payload_,\n        bytes calldata adapterParams_,\n        uint256 originalValue_\n    ) external onlyOwner nonReentrant {\n        ensureNonzeroAddress(to_);\n        require(originalValue_ > 0, \"OmnichainProposalSender: invalid native amount\");\n        require(payload_.length != 0, \"OmnichainProposalSender: empty payload\");\n\n        bytes32 hash = storedExecutionHashes[pId_];\n        require(hash != bytes32(0), \"OmnichainProposalSender: no stored payload\");\n\n        bytes memory execution = abi.encode(remoteChainId_, payload_, adapterParams_, originalValue_);\n        require(keccak256(execution) == hash, \"OmnichainProposalSender: invalid execution params\");\n\n        delete storedExecutionHashes[pId_];\n\n        emit FallbackWithdraw(to_, originalValue_);\n        emit ClearPayload(pId_, hash);\n\n        // Transfer the native to the `to_` address\n        (bool sent, ) = to_.call{ value: originalValue_ }(\"\");\n        require(sent, \"Call failed\");\n    }\n\n    /**\n     * @notice Sets the remote message receiver address\n     * @param remoteChainId_ The LayerZero id of a remote chain\n     * @param newRemoteAddress_ The address of the contract on the remote chain to receive messages sent by this contract\n     * @custom:access Controlled by AccessControlManager\n     * @custom:event Emits SetTrustedRemoteAddress with remote chain Id and remote address\n     */\n    function setTrustedRemoteAddress(uint16 remoteChainId_, bytes calldata newRemoteAddress_) external {\n        // _ensureAllowed(\"setTrustedRemoteAddress(uint16,bytes)\");\n        require(remoteChainId_ != 0, \"OmnichainProposalSender: chainId must not be zero\");\n        ensureNonzeroAddress(address(uint160(bytes20(newRemoteAddress_))));\n        require(newRemoteAddress_.length == 20, \"OmnichainProposalSender: remote address must be 20 bytes long\");\n        bytes memory oldRemoteAddress = trustedRemoteLookup[remoteChainId_];\n        trustedRemoteLookup[remoteChainId_] = abi.encodePacked(newRemoteAddress_, address(this));\n        emit SetTrustedRemoteAddress(remoteChainId_, oldRemoteAddress, trustedRemoteLookup[remoteChainId_]);\n    }\n\n    /**\n     * @notice Sets the configuration of the LayerZero messaging library of the specified version\n     * @param version_ Messaging library version\n     * @param chainId_ The LayerZero chainId for the pending config change\n     * @param configType_ The type of configuration. Every messaging library has its own convention\n     * @param config_ The configuration in bytes. It can encode arbitrary content\n     * @custom:access Controlled by AccessControlManager\n     */\n    function setConfig(uint16 version_, uint16 chainId_, uint256 configType_, bytes calldata config_) external {\n        // _ensureAllowed(\"setConfig(uint16,uint16,uint256,bytes)\");\n        LZ_ENDPOINT.setConfig(version_, chainId_, configType_, config_);\n    }\n\n    /**\n     * @notice Sets the configuration of the LayerZero messaging library of the specified version\n     * @param version_ New messaging library version\n     * @custom:access Controlled by AccessControlManager\n     */\n    function setSendVersion(uint16 version_) external {\n        // _ensureAllowed(\"setSendVersion(uint16)\");\n        LZ_ENDPOINT.setSendVersion(version_);\n    }\n\n    /**\n     * @notice Gets the configuration of the LayerZero messaging library of the specified version\n     * @param version_ Messaging library version\n     * @param chainId_ The LayerZero chainId\n     * @param configType_ Type of configuration. Every messaging library has its own convention\n     */\n    function getConfig(uint16 version_, uint16 chainId_, uint256 configType_) external view returns (bytes memory) {\n        return LZ_ENDPOINT.getConfig(version_, chainId_, address(this), configType_);\n    }\n\n    function _validateProposal(uint16 remoteChainId_, bytes memory payload_) internal {\n        (\n            address[] memory targets,\n            uint256[] memory values,\n            string[] memory signatures,\n            bytes[] memory calldatas,\n\n        ) = abi.decode(payload_, (address[], uint[], string[], bytes[], uint8));\n        require(\n            targets.length == values.length &&\n                targets.length == signatures.length &&\n                targets.length == calldatas.length,\n            \"OmnichainProposalSender: proposal function information arity mismatch\"\n        );\n        _isEligibleToSend(remoteChainId_, targets.length);\n    }\n}\n"
    },
    "contracts/Governance/IAccessControlManagerV8.sol": {
      "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport \"@openzeppelin/contracts/access/IAccessControl.sol\";\n\n/**\n * @title IAccessControlManagerV8\n * @author Venus\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\n */\ninterface IAccessControlManagerV8 is IAccessControl {\n    function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\n\n    function revokeCallPermission(\n        address contractAddress,\n        string calldata functionSig,\n        address accountToRevoke\n    ) external;\n\n    function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\n\n    function hasPermission(\n        address account,\n        address contractAddress,\n        string calldata functionSig\n    ) external view returns (bool);\n}\n"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 10000
    },
    "evmVersion": "shanghai",
    "outputSelection": {
      "*": {
        "*": [
          "storageLayout",
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata",
          "devdoc",
          "userdoc",
          "evm.gasEstimates"
        ],
        "": ["ast"]
      }
    },
    "metadata": {
      "useLiteralContent": true
    }
  }
}
