{"file_path":"contracts/CollateralVault.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: UNLICENSED\r\npragma solidity 0.8.23;\r\n\r\nimport '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol';\r\nimport '@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol';\r\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\r\nimport './interfaces/ISubVault.sol';\r\nimport './interfaces/ICollateralVault.sol';\r\nimport './interfaces/access/IAccessController.sol';\r\nimport './utils/Constants.sol';\r\nimport './libraries/SystemRoles.sol';\r\nimport './utils/AccessChecker.sol';\r\nimport './interfaces/access/IRegistry.sol';\r\nimport './interfaces/IZeUSD_CDP.sol';\r\n\r\n/**\r\n * @title Collateral Vault\r\n * @author ZeUSD Protocol Team\r\n * @notice Manages user collateral deposits and tracks asset configurations\r\n * @dev Implements UUPS upgradeable pattern and handles deposit tracking\r\n * @custom:security-contact paras@zoth.io\r\n *\r\n * Security Considerations:\r\n * - Role-based access control for admin functions\r\n * - Deposit tracking integrity\r\n * - Pausable for emergency situations\r\n * - Upgradeable pattern safety\r\n * - Zero address validations\r\n * - Authorized subvault validations\r\n *\r\n * Role Capabilities:\r\n * DEFAULT_ADMIN_ROLE:\r\n * - Can grant/revoke all roles\r\n * - Can upgrade contract\r\n * - Can perform all admin functions\r\n *\r\n * ADMIN_ROLE:\r\n * - Can configure assets\r\n * - Can authorize subvaults\r\n * - Can pause/unpause operations\r\n * - Cannot grant/revoke roles\r\n *\r\n * State Management:\r\n * Normal Operation:\r\n * - Deposits accepted from authorized subvaults\r\n * - Asset configurations modifiable\r\n * - Full tracking functionality\r\n *\r\n * Paused State:\r\n * - No new deposits\r\n * - Admin functions still active\r\n * - View functions available\r\n *\r\n * Upgrade Safety:\r\n * Storage Layout:\r\n * - Asset configurations\r\n * - User deposits\r\n * - Access control state\r\n * New variables must be appended\r\n */\r\ncontract CollateralVault is ICollateralVault, Initializable, UUPSUpgradeable, PausableUpgradeable {\r\n    /// @notice Router contract address for deposit operations\r\n    /// @dev Only router can initiate deposits\r\n    address public router;\r\n\r\n    /// @notice Fixed price for stable assets\r\n    /// @dev Used when oracle price is unavailable\r\n    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\r\n    uint256 public immutable STABLE_PRICE = 1e6;\r\n\r\n    /// @notice Mapping of Integrated SubVaults\r\n    /// @dev Stores all registered SubVaults and their configurations\r\n    mapping(address => DataTypes.CollateralDetails) public collateralDetails;\r\n\r\n    // @notice Array to track all registered collateral addresses\r\n    address[] private registeredCollaterals;\r\n\r\n    /// @notice Access controller contract reference\r\n    /// @dev Used for role checks\r\n    IAccessController public accessController;\r\n\r\n    /// @notice Deposit NFT contract reference\r\n    /// @dev Used for position tracking\r\n    IZeUSD_CDP public depositNFT;\r\n\r\n    /**\r\n     * @notice Ensures caller is the authorized router\r\n     * @dev Used for deposit operations, checks if msg.sender matches router address\r\n     * @custom:security Critical for deposit validation\r\n     */\r\n    modifier onlyRouter() {\r\n        if (msg.sender != router) {\r\n            revert UnauthorizedRouter(msg.sender);\r\n        }\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @notice Validates address is not zero\r\n     * @dev Used for input validation\r\n     * @param addr Address to validate\r\n     * @custom:security Prevents zero address operations\r\n     */\r\n    modifier validAddress(address addr) {\r\n        if (addr == address(0)) {\r\n            revert InvalidAddress(addr);\r\n        }\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @notice Initializes the vault contract\r\n     * @dev Sets up initial admin and roles\r\n     * @custom:security Only callable once\r\n     * @custom:emits RoleGranted events\r\n     */\r\n    function initialize(address registryContract, address _router) external initializer {\r\n        __UUPSUpgradeable_init();\r\n        __Pausable_init();\r\n        if (registryContract == address(0)) revert InvalidAddress(registryContract);\r\n        if (_router == address(0)) revert InvalidAddress(_router);\r\n        router = _router;\r\n        accessController = IAccessController(\r\n            IRegistry(registryContract).getContract(Constants.CONTRACT_ACCESS_CONTROLLER)\r\n        );\r\n        depositNFT = IZeUSD_CDP(\r\n            IRegistry(registryContract).getContract(Constants.CONTRACT_DEPOSIT_NFT)\r\n        );\r\n    }\r\n\r\n    /**\r\n     * @notice Sets the router address\r\n     * @dev Can only be set once by admin\r\n     * @param newRouter Address of the router contract\r\n     * @custom:security Validates router address\r\n     * @custom:emits RouterUpdated\r\n     */\r\n    function setRouter(address newRouter) external {\r\n        AccessChecker.checkRole(accessController, SystemRoles.DEFAULT_ADMIN_ROLE, msg.sender);\r\n        if (newRouter == address(0)) revert InvalidAddress(newRouter);\r\n        router = newRouter;\r\n        emit RouterUpdated(newRouter);\r\n    }\r\n\r\n    /**\r\n     * @notice Registers or updates a subvault configuration\r\n     * @dev Validates and stores subvault configuration with collateral details\r\n     * @param integrationType Type of integration\r\n     * @param collateralAddress Address of the primary/collateral asset\r\n     * @param subVaultAddress Address of the subvault\r\n     * @param price Price of the collateral\r\n     * @param ltv Loan to value ratio\r\n     * @param isActive Whether the subvault is active\r\n     * @param tokenType Classification of the collateral token\r\n     * @custom:security Access controlled by VAULT_ADMIN_ROLE\r\n     * @custom:emits SubVaultRegistered\r\n     */\r\n    function registerSubVault(\r\n        string calldata integrationType,\r\n        address collateralAddress,\r\n        address subVaultAddress,\r\n        uint256 price,\r\n        uint256 ltv,\r\n        bool isActive,\r\n        DataTypes.TokenType tokenType\r\n    ) external {\r\n        AccessChecker.checkRole(accessController, SystemRoles.VAULT_ADMIN_ROLE, msg.sender);\r\n        // Input validation\r\n        if (bytes(integrationType).length == 0) revert InvalidParameters('Empty integration type');\r\n        if (collateralAddress == address(0)) revert InvalidAddress(collateralAddress);\r\n        if (subVaultAddress == address(0)) revert InvalidAddress(subVaultAddress);\r\n        if (price == 0) revert InvalidPrice();\r\n        if (ltv == 0 || ltv > 1000000) revert InvalidLTV();\r\n\r\n        // Check if another subvault exists for this collateral\r\n        if (\r\n            collateralDetails[collateralAddress].subVaultAddress != address(0) &&\r\n            collateralDetails[collateralAddress].subVaultAddress != subVaultAddress\r\n        ) {\r\n            revert SubVaultAlreadyRegistered(\r\n                collateralAddress,\r\n                collateralDetails[collateralAddress].subVaultAddress\r\n            );\r\n        }\r\n\r\n        // Update collateral details with new configuration\r\n        collateralDetails[collateralAddress] = DataTypes.CollateralDetails({\r\n            integrationType: integrationType,\r\n            collateralAddress: collateralAddress,\r\n            subVaultAddress: subVaultAddress,\r\n            price: price,\r\n            ltv: ltv,\r\n            isActive: isActive,\r\n            registeredAt: block.timestamp,\r\n            lastUpdatedAt: block.timestamp,\r\n            tokenType: tokenType\r\n        });\r\n\r\n        // Add to registered collaterals if not already present\r\n        registeredCollaterals.push(collateralAddress);\r\n\r\n        // Emit event with updated configuration\r\n        emit SubVaultRegistered(\r\n            collateralAddress,\r\n            subVaultAddress,\r\n            integrationType,\r\n            price,\r\n            ltv,\r\n            isActive,\r\n            tokenType\r\n        );\r\n    }\r\n\r\n    /**\r\n     * @notice Updates specific parameters of a subvault\r\n     * @dev Only RISK_CONTROLLER_ROLE can update parameters\r\n     * @param collateralAddress Address of the collateral asset\r\n     * @param params Update parameters structure\r\n     * @custom:security Access controlled by RISK_CONTROLLER_ROLE\r\n     * @custom:emits SubVaultUpdated\r\n     */\r\n    function updateSubVaultConfig(\r\n        address collateralAddress,\r\n        DataTypes.SubVaultUpdateParams calldata params\r\n    ) external {\r\n        AccessChecker.checkRole(accessController, SystemRoles.RISK_CONTROLLER_ROLE, msg.sender);\r\n        DataTypes.CollateralDetails storage details = collateralDetails[collateralAddress];\r\n        if (details.subVaultAddress == address(0)) revert AssetNotSupported(collateralAddress);\r\n\r\n        if (params.updatePrice) {\r\n            if (params.price == 0) revert InvalidPrice();\r\n            details.price = params.price;\r\n        }\r\n\r\n        if (params.updateLTV) {\r\n            if (params.ltv == 0 || params.ltv > 1000000) revert InvalidLTV();\r\n            details.ltv = params.ltv;\r\n        }\r\n\r\n        if (params.updateActive) {\r\n            details.isActive = params.isActive;\r\n        }\r\n\r\n        details.lastUpdatedAt = block.timestamp;\r\n\r\n        emit SubVaultUpdated(\r\n            collateralAddress,\r\n            details.subVaultAddress,\r\n            details.price,\r\n            details.ltv,\r\n            details.isActive\r\n        );\r\n    }\r\n\r\n    /**\r\n     * @notice Calculates mint amount for given collateral\r\n     * @dev Handles both stable and non-stable token calculations\r\n     * @param collateralAddress Collateral token address\r\n     * @param asset Asset token address\r\n     * @param tokenType Type of token (stable/non-stable)\r\n     * @param amount Amount of collateral\r\n     * @return mintAmount Final mint amount\r\n     * @custom:security Requires active subvault and valid price\r\n     */\r\n    function calculateMintAmount(\r\n        address collateralAddress,\r\n        address asset,\r\n        DataTypes.TokenType tokenType,\r\n        uint256 amount\r\n    ) public view whenNotPaused returns (uint256 mintAmount) {\r\n        if (collateralAddress == address(0)) revert InvalidAddress(collateralAddress);\r\n        if (amount == 0) revert InvalidAmount();\r\n\r\n        address subvault = getSubVaultAddress(collateralAddress);\r\n        if (subvault == address(0)) revert AssetNotSupported(collateralAddress);\r\n\r\n        DataTypes.CollateralDetails storage details = collateralDetails[collateralAddress];\r\n        if (!details.isActive || details.subVaultAddress != subvault) {\r\n            revert UnauthorizedSubVault(subvault);\r\n        }\r\n\r\n        uint256 assetPrice;\r\n        bool success;\r\n\r\n        if (tokenType == DataTypes.TokenType.StableCoin) {\r\n            if (!ISubVault(subvault).isAssetSupported(asset)) revert AssetNotSupported(asset);\r\n            (uint256 oraclePrice, bool priceSuccess) = ISubVault(subvault).getOraclePrice(asset);\r\n            success = priceSuccess;\r\n            assetPrice = success ? oraclePrice / 100 : STABLE_PRICE;\r\n        } else {\r\n            (uint256 oraclePrice, bool priceSuccess) = ISubVault(subvault).getOraclePrice(\r\n                collateralAddress\r\n            );\r\n            success = priceSuccess;\r\n            assetPrice = success ? oraclePrice / 100 : details.price;\r\n        }\r\n\r\n        return _scaleAmount(_calculateMintAmount(amount, assetPrice, details.ltv), asset);\r\n    }\r\n\r\n    /**\r\n     * @notice Validates deposit parameters and prepares metadata\r\n     * @dev Only callable by router when system is not paused\r\n     * @param user Address of the depositing user\r\n     * @param collateralAddress Address of collateral asset\r\n     * @param asset Address of the asset being deposited\r\n     * @param amount Amount being deposited\r\n     * @param tokenId NFT token ID of the deposit\r\n     * @return metadata Deposit metadata structure\r\n     * @custom:security Validates active subvault and amounts\r\n     */\r\n    function validateAndPrepareDeposit(\r\n        address user,\r\n        address collateralAddress,\r\n        address asset,\r\n        uint256 amount,\r\n        uint256 tokenId\r\n    ) external view onlyRouter whenNotPaused returns (DataTypes.DepositMetadata memory metadata) {\r\n        if (amount == 0) revert InvalidAmount();\r\n        if (user == address(0)) revert InvalidAddress(user);\r\n\r\n        DataTypes.CollateralDetails memory details = collateralDetails[collateralAddress];\r\n        if (!details.isActive) revert SubVaultNotActive();\r\n        if (details.subVaultAddress == address(0)) revert AssetNotSupported(collateralAddress);\r\n\r\n        uint256 assetPrice;\r\n        uint256 collateralPrice;\r\n        uint256 mintAmount;\r\n        bool success;\r\n        DataTypes.TokenType tokenType;\r\n\r\n        (collateralPrice, success) = ISubVault(details.subVaultAddress).getOraclePrice(\r\n            collateralAddress\r\n        );\r\n        if (asset == collateralAddress) {\r\n            assetPrice = success ? collateralPrice / 100 : details.price;\r\n            mintAmount = _calculateMintAmount(amount, assetPrice, details.ltv);\r\n            tokenType = DataTypes.TokenType.NotStableCoin;\r\n        } else {\r\n            if (!ISubVault(details.subVaultAddress).isAssetSupported(asset))\r\n                revert AssetNotSupported(asset);\r\n            (uint256 oraclePrice, bool successStable) = ISubVault(details.subVaultAddress)\r\n                .getOraclePrice(asset);\r\n            assetPrice = successStable ? oraclePrice / 100 : STABLE_PRICE;\r\n            mintAmount = _calculateMintAmount(amount, assetPrice, details.ltv);\r\n            tokenType = DataTypes.TokenType.StableCoin;\r\n        }\r\n\r\n        uint256 scaledMintAmount = _scaleAmount(mintAmount, asset);\r\n\r\n        return\r\n            DataTypes.DepositMetadata({\r\n                issuer: user,\r\n                collateralAddress: collateralAddress,\r\n                asset: asset,\r\n                amount: amount,\r\n                zeusdMinted: scaledMintAmount,\r\n                depositTimestamp: block.timestamp,\r\n                tokenId: tokenId,\r\n                collateralPrice: collateralPrice / 100,\r\n                subVault: details.subVaultAddress,\r\n                integrationType: details.integrationType,\r\n                tokenType: tokenType\r\n            });\r\n    }\r\n\r\n    /**\r\n     * @notice Calculates mint amount with overflow protection\r\n     * @dev Uses assembly for gas-efficient overflow checks\r\n     * @param amount Amount of collateral\r\n     * @param price Price of collateral\r\n     * @param ltv Loan to value ratio (1-1000000)\r\n     * @return mintAmount Amount to mint\r\n     * @custom:security Includes overflow protection\r\n     */\r\n    function _calculateMintAmount(\r\n        uint256 amount,\r\n        uint256 price,\r\n        uint256 ltv\r\n    ) internal pure returns (uint256 mintAmount) {\r\n        assembly {\r\n            let collateralValue := mul(amount, price)\r\n            if iszero(eq(div(collateralValue, amount), price)) {\r\n                revert(0, 0)\r\n            }\r\n            mintAmount := div(mul(collateralValue, ltv), 1000000)\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Optimized scaling of mint amount based on decimals\r\n     * @dev Pre-calculates power of 10 for common decimal values\r\n     * @param mintAmount Amount to scale\r\n     * @param asset Token address\r\n     * @return scaledAmount Scaled amount\r\n     * @custom:security Handles decimal conversion safely\r\n     */\r\n    function _scaleAmount(\r\n        uint256 mintAmount,\r\n        address asset\r\n    ) internal view returns (uint256 scaledAmount) {\r\n        uint8 decimal = ERC20(asset).decimals();\r\n\r\n        uint64[19] memory POWERS_OF_TEN = [\r\n            1e0,\r\n            1e1,\r\n            1e2,\r\n            1e3,\r\n            1e4,\r\n            1e5,\r\n            1e6,\r\n            1e7,\r\n            1e8,\r\n            1e9,\r\n            1e10,\r\n            1e11,\r\n            1e12,\r\n            1e13,\r\n            1e14,\r\n            1e15,\r\n            1e16,\r\n            1e17,\r\n            1e18\r\n        ];\r\n\r\n        uint256 offset = decimal + 6;\r\n        if (offset > 6) {\r\n            uint256 scale = POWERS_OF_TEN[offset - 6];\r\n            return mintAmount / scale;\r\n        } else if (offset < 6) {\r\n            uint256 scale = POWERS_OF_TEN[6 - offset];\r\n            return mintAmount * scale;\r\n        }\r\n        return mintAmount;\r\n    }\r\n\r\n    /**\r\n     * @notice Returns all registered subvaults and their details\r\n     * @dev Returns arrays of equal length containing vault data\r\n     * @return collaterals Array of collateral addresses\r\n     * @return details Array of corresponding CollateralDetails\r\n     */\r\n    function getAllSubVaults()\r\n        external\r\n        view\r\n        returns (address[] memory collaterals, DataTypes.CollateralDetails[] memory details)\r\n    {\r\n        uint256 length = registeredCollaterals.length;\r\n        details = new DataTypes.CollateralDetails[](length);\r\n\r\n        for (uint256 i = 0; i < length; i++) {\r\n            details[i] = collateralDetails[registeredCollaterals[i]];\r\n        }\r\n\r\n        return (registeredCollaterals, details);\r\n    }\r\n\r\n    /**\r\n     * @notice Returns all active subvaults and their details\r\n     * @dev Filters and returns only active vault configurations\r\n     * @return collaterals Array of active collateral addresses\r\n     * @return details Array of corresponding CollateralDetails\r\n     */\r\n    function getActiveSubVaults()\r\n        external\r\n        view\r\n        returns (address[] memory collaterals, DataTypes.CollateralDetails[] memory details)\r\n    {\r\n        uint256 length = registeredCollaterals.length;\r\n        uint256 activeCount = 0;\r\n        for (uint256 i = 0; i < length; i++) {\r\n            if (collateralDetails[registeredCollaterals[i]].isActive) {\r\n                activeCount++;\r\n            }\r\n        }\r\n\r\n        address[] memory activeCollaterals = new address[](activeCount);\r\n        DataTypes.CollateralDetails[] memory activeDetails = new DataTypes.CollateralDetails[](\r\n            activeCount\r\n        );\r\n\r\n        uint256 index = 0;\r\n        for (uint256 i = 0; i < length; i++) {\r\n            address collateral = registeredCollaterals[i];\r\n            if (collateralDetails[collateral].isActive) {\r\n                activeCollaterals[index] = collateral;\r\n                activeDetails[index] = collateralDetails[collateral];\r\n                index++;\r\n            }\r\n        }\r\n\r\n        return (activeCollaterals, activeDetails);\r\n    }\r\n\r\n    /**\r\n     * @notice Gets subvault address for a collateral asset\r\n     * @dev Reverts if subvault is not active\r\n     * @param collateralAddress Address of the collateral asset\r\n     * @return subVaultAddress Address of the corresponding subvault\r\n     * @custom:security Validates subvault active status\r\n     */\r\n    function getSubVaultAddress(\r\n        address collateralAddress\r\n    ) public view returns (address subVaultAddress) {\r\n        DataTypes.CollateralDetails memory details = collateralDetails[collateralAddress];\r\n        if (!details.isActive) revert SubVaultNotActive();\r\n        return details.subVaultAddress;\r\n    }\r\n\r\n    /**\r\n     * @notice Gets all details for a collateral asset's subvault\r\n     * @dev Returns full configuration details\r\n     * @param collateralAddress Address of the collateral asset\r\n     * @return details Full configuration details\r\n     */\r\n    function getSubVaultDetails(\r\n        address collateralAddress\r\n    ) external view returns (DataTypes.CollateralDetails memory details) {\r\n        return collateralDetails[collateralAddress];\r\n    }\r\n\r\n    /**\r\n     * @notice Returns count of all registered subvaults\r\n     * @dev Provides both total and active counts\r\n     * @return total Total number of registered subvaults\r\n     * @return active Number of active subvaults\r\n     */\r\n    function getSubVaultCounts() external view returns (uint256 total, uint256 active) {\r\n        total = registeredCollaterals.length;\r\n        for (uint256 i = 0; i < total; i++) {\r\n            if (collateralDetails[registeredCollaterals[i]].isActive) {\r\n                active++;\r\n            }\r\n        }\r\n        return (total, active);\r\n    }\r\n\r\n    /**\r\n     * @notice Removes a subvault registration\r\n     * @dev Only VAULT_ADMIN_ROLE can remove subvaults\r\n     * @param collateralAddress The collateral asset address of the subvault to remove\r\n     * @custom:security Access controlled by VAULT_ADMIN_ROLE\r\n     * @custom:emits SubVaultRemoved\r\n     */\r\n    function removeSubVault(address collateralAddress) external {\r\n        AccessChecker.checkRole(accessController, SystemRoles.VAULT_ADMIN_ROLE, msg.sender);\r\n        if (collateralDetails[collateralAddress].subVaultAddress == address(0)) {\r\n            revert AssetNotSupported(collateralAddress);\r\n        }\r\n\r\n        address subVaultAddress = collateralDetails[collateralAddress].subVaultAddress;\r\n\r\n        // Remove from registeredCollaterals array\r\n        for (uint256 i = 0; i < registeredCollaterals.length; i++) {\r\n            if (registeredCollaterals[i] == collateralAddress) {\r\n                registeredCollaterals[i] = registeredCollaterals[registeredCollaterals.length - 1];\r\n                registeredCollaterals.pop();\r\n                break;\r\n            }\r\n        }\r\n\r\n        delete collateralDetails[collateralAddress];\r\n\r\n        emit SubVaultRemoved(collateralAddress, subVaultAddress);\r\n    }\r\n\r\n    /**\r\n     * @notice Gets all registered collateral addresses\r\n     * @return Array of collateral addresses\r\n     */\r\n    function getRegisteredCollaterals() external view returns (address[] memory) {\r\n        return registeredCollaterals;\r\n    }\r\n\r\n    /**\r\n     * @notice Pauses vault operations\r\n     * @dev Only callable by DEFAULT_ADMIN_ROLE\r\n     * @custom:security Access controlled operation\r\n     */\r\n    function pause() external {\r\n        AccessChecker.checkRole(accessController, SystemRoles.RISK_CONTROLLER_ROLE, msg.sender);\r\n        _pause();\r\n    }\r\n\r\n    /**\r\n     * @notice Unpauses vault operations\r\n     * @dev Only callable by DEFAULT_ADMIN_ROLE\r\n     * @custom:security Access controlled operation\r\n     */\r\n    function unpause() external {\r\n        AccessChecker.checkRole(accessController, SystemRoles.RISK_CONTROLLER_ROLE, msg.sender);\r\n        _unpause();\r\n    }\r\n\r\n    /**\r\n     * @notice Authorizes contract upgrades\r\n     * @dev Only callable by UPGRADER_ROLE\r\n     * @custom:security Critical upgrade operation\r\n     */\r\n    function _authorizeUpgrade(address /*newImplementation*/) internal view override {\r\n        AccessChecker.checkRole(accessController, SystemRoles.UPGRADER_ROLE, msg.sender);\r\n    }\r\n\r\n    /**\r\n     * @notice Gets user active positions for a specific subvault\r\n     * @param user Address to query positions for\r\n     * @param subVault Subvault to filter by\r\n     * @return metadata Array of active deposit metadata\r\n     */\r\n    function getUserActivePositionsBySubVault(\r\n        address user,\r\n        address subVault\r\n    ) external view override returns (DataTypes.DepositMetadata[] memory metadata) {\r\n        uint256[] memory allTokens = depositNFT.getTokensByOwner(user);\r\n        uint256 matchCount = 0;\r\n\r\n        // Count matching active positions first\r\n        for (uint256 i = 0; i < allTokens.length; i++) {\r\n            DataTypes.DepositMetadata memory details = depositNFT.getDepositDetails(allTokens[i]);\r\n            if (details.subVault == subVault) {\r\n                matchCount++;\r\n            }\r\n        }\r\n\r\n        // Create and fill array with matching active positions\r\n        metadata = new DataTypes.DepositMetadata[](matchCount);\r\n        uint256 index = 0;\r\n        for (uint256 i = 0; i < allTokens.length; i++) {\r\n            DataTypes.DepositMetadata memory details = depositNFT.getDepositDetails(allTokens[i]);\r\n            if (details.subVault == subVault) {\r\n                metadata[index] = details;\r\n                index++;\r\n            }\r\n        }\r\n\r\n        return metadata;\r\n    }\r\n}\r\n","deployed_bytecode":"0x6080604052600436101561001257600080fd5b60003560e01c8063191614e1146101a757806338df2ff3146101a25780633f4ba83a1461019d578063485cc955146101985780634cd36c66146101935780634f1ef2861461018e57806352d1902d1461018957806357453d06146101845780635c975abb1461017f578063618c373e1461017a57806367e3c4d4146101755780636fb07afc146101705780637fcf21561461016b5780638456cb591461016657806387fe819b1461016157806395f9e2d21461015c578063a878fa9014610157578063ac848eab14610152578063ad3cb1cc1461014d578063bc43cbaf14610148578063c08dc8fd14610143578063c0d786551461013e578063c74b031d14610139578063ee747f1d146101345763f887ea401461012f57600080fd5b611efc565b611e19565b611d06565b611bda565b6118aa565b611881565b611829565b61167b565b6114c3565b611443565b6113c5565b611321565b6112e6565b6110cf565b611042565b610bfa565b610b10565b610ad7565b610a6c565b6108e6565b610804565b6106e2565b610637565b6105b2565b610360565b90815180825260208080930193019160005b8281106101cc575050505090565b83516001600160a01b0316855293810193928101926001016101be565b60005b8381106101fc5750506000910152565b81810151838201526020016101ec565b90602091610225815180928185528580860191016101e9565b601f01601f1916010190565b6002111561023b57565b634e487b7160e01b600052602160045260246000fd5b90600282101561023b5752565b906102e79061027761012084519080845283019061020c565b6020808501516001600160a01b0390811691840191909152604080860151909116908301529260608101516060830152608081015160808301526102c460a082015160a084019015159052565b60c081015160c083015260e081015160e083015261010080910151910190610251565b90565b906102fd906040835260408301906101ac565b90602090818184039101528251908183528083019281808460051b8301019501936000915b8483106103325750505050505090565b9091929394958480610350600193601f198682030187528a5161025e565b9801930193019194939290610322565b346103f1576000806003193601126103ee5760025461037e81611f93565b91805b8281106103a457836103916120da565b6103a0604051928392836102ea565b0390f35b600190818060a01b038160008051602061338f8339815191520154168352816020526103d260408420612043565b6103dc8287612023565b526103e78186612023565b5001610381565b80fd5b600080fd5b6001600160a01b038116036103f157565b60243590610414826103f6565b565b60443590610414826103f6565b6001600160a01b0316600090815260016020526040902090565b90600182811c9216801561046d575b602083101461045757565b634e487b7160e01b600052602260045260246000fd5b91607f169161044c565b634e487b7160e01b600052604160045260246000fd5b90601f801991011681019081106001600160401b038211176104ae57604052565b610477565b906040519182600082546104c68161043d565b9081845260209460019160018116908160001461053457506001146104f5575b5050506104149250038361048d565b600090815285812095935091905b81831061051c57505061041493508201013880806104e6565b85548884018501529485019487945091830191610503565b9250505061041494925060ff191682840152151560051b8201013880806104e6565b94909361010096926105796104149a969c9b99959c610120808a5289019061020c565b6001600160a01b0391821660208901529b16604087015260608601526080850152151560a084015260c083015260e08201520190610251565b346103f15760203660031901126103f1576004356105cf816103f6565b6001600160a01b0390811660009081526001602052604090206103a06105f4826104b3565b918360018201541693600282015416906003810154600482015460ff6005840154169060068401549260ff600860078701549601541695604051998a998a610556565b346103f15760003660031901126103f15760035461065f9033906001600160a01b0316612d1e565b6000805160206133cf833981519152805460ff8116156106ab5760ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b604051638dfc202b60e01b8152600490fd5b60409060031901126103f1576004356106d5816103f6565b906024356102e7816103f6565b346103f1576106f0366106bd565b906000805160206133ef83398151915254916001600160401b0360ff8460401c16159316801590816107fc575b60011490816107f2575b1590816107e9575b506107d7576000805160206133ef833981519152805467ffffffffffffffff1916600117905561076391836107b25761216b565b61076957005b6000805160206133ef833981519152805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b6000805160206133ef833981519152805460ff60401b1916600160401b17905561216b565b60405163f92ee8a960e01b8152600490fd5b9050153861072f565b303b159150610727565b84915061071d565b346103f15760003660031901126103f1576103a06108206120da565b6040519182916020835260208301906101ac565b6040519061016082018281106001600160401b038211176104ae57604052565b6040519061012082018281106001600160401b038211176104ae57604052565b6040519061026082018281106001600160401b038211176104ae57604052565b6001600160401b0381116104ae57601f01601f191660200190565b9291926108bb82610894565b916108c9604051938461048d565b8294818452818301116103f1578281602093846000960137010152565b60403660031901126103f1576004803590610900826103f6565b6024356001600160401b0381116103f157366023820112156103f15761092f90369060248185013591016108af565b6001600160a01b037f000000000000000000000000fdfc611e17298df89c0ff6ef9c5059a4bd9602b18116308114908115610a50575b50610a3f579060208261097e8594600354163390612df6565b6040516352d1902d60e01b8152938491829088165afa60009281610a0e575b506109cf575050604051634c9c8ce360e01b81526001600160a01b0390921690820190815281906020010390fd5b0390fd5b83836000805160206133af83398151915284036109f2576109f08383613242565b005b604051632a87526960e21b815290810184815281906020010390fd5b610a3191935060203d602011610a38575b610a29818361048d565b810190612fcf565b913861099d565b503d610a1f565b60405163703e46dd60e11b81528390fd5b9050816000805160206133af8339815191525416141538610965565b346103f15760003660031901126103f1577f000000000000000000000000fdfc611e17298df89c0ff6ef9c5059a4bd9602b16001600160a01b03163003610ac55760206040516000805160206133af8339815191528152f35b60405163703e46dd60e11b8152600490fd5b346103f15760203660031901126103f1576020610afe600435610af9816103f6565b612305565b6040516001600160a01b039091168152f35b346103f15760003660031901126103f157602060ff6000805160206133cf83398151915254166040519015158152f35b80516001600160a01b03168252906102e790610bd96101606020858101516001600160a01b0316908401526040858101516001600160a01b031690840152606085810151908401526080808601519084015260a0808601519084015260c0808601519084015260e08086015190840152610100808601516001600160a01b0316908401526101209080828701519285015283019061020c565b9261014080910151910190610251565b9060206102e7928181520190610b40565b346103f15760a03660031901126103f1576004803590610c19826103f6565b60243590610c26826103f6565b60443591610c33836103f6565b606435610c3e6123d5565b50600080549093906001600160a01b03908116330361102b57610c5f612fde565b821561101b5780871615610ff5576001600160a01b0384166000908152600160205260409020610c9390612043565b612043565b92610ca8610ca460a0860151151590565b1590565b610fe45760409687850192610cd2610cc6855160018060a01b031690565b6001600160a01b031690565b15610fbf5783518790610cef90610cc6906001600160a01b031681565b8a51631d7d882b60e21b8082526001600160a01b039093168189019081529097918c918991908290819060200103915afa928315610f40578a978b94610f9a575b50848116908a1603610dff57505015610dee57610d6081610d5b606487045b60808901519086613009565b61305c565b92516001600160a01b0316945195610d76610834565b6001600160a01b03909a168a526001600160a01b031660208a01526001600160a01b031688880152606088015260808701524260a087015260843560c08701526064900460e08601526001600160a01b0316610100850152610120840152610de2906101408401612037565b516103a0819282610be9565b610d6081610d5b6060880151610d4f565b909150610e4c602084610e21610cc6610cc68a9e989e5160018060a01b031690565b8d516308c9682b60e31b81526001600160a01b03909216858301908152919384928391829160200190565b03915afa908115610f40578491610f6b575b5015610f45578451610ea893928b928b92610e8390610cc6906001600160a01b031681565b84519283526001600160a01b0390931690820190815290948592918391829160200190565b03915afa908115610f405780928192610f0e575b505015610ee4576064610ed791045b60808601519083613009565b95610d608160019861305c565b50610ed77f00000000000000000000000000000000000000000000000000000000000f4240610ecb565b909250610f319150893d8b11610f39575b610f29818361048d565b81019061243a565b909138610ebc565b503d610f1f565b61215f565b8951632777a68f60e11b81526001600160a01b038a169181019182529081906020010390fd5b610f8d915060203d602011610f93575b610f85818361048d565b810190612456565b38610e5e565b503d610f7b565b909350610fb59197508b3d8d11610f3957610f29818361048d565b9690969238610d30565b8851632777a68f60e11b81526001600160a01b03881681870190815281906020010390fd5b60405163169652d560e01b81528390fd5b604051634726455360e11b81526001600160a01b03881681840190815281906020010390fd5b5060405163162908e360e11b8152fd5b6040516305f112b360e41b81523381840152602490fd5b346103f15760003660031901126103f1576004546040516001600160a01b039091168152602090f35b6020808201906020835283518092526040830192602060408460051b8301019501936000915b8483106110a15750505050505090565b90919293949584806110bf600193603f198682030187528a51610b40565b9801930193019194939290611091565b346103f15761112a6110e0366106bd565b600480549091906110f9906001600160a01b0316610cc6565b604080516340398d6760e01b81526001600160a01b0390951660048601526000959091908690869081906024820190565b0381845afa948515610f405786956112c2575b508593865b86518110156111f25761117788611159838a612023565b5186518093819263890db72f60e01b83528783019190602083019252565b0381875afa908115610f40576111a191610100918b916111d0575b5001516001600160a01b031690565b6001600160a01b038681169116146111bc575b600101611142565b946111c860019161263e565b9590506111b4565b6111ec91503d808d833e6111e4818361048d565b810190612567565b38611192565b509194926112008795612652565b918593865b86518110156112b45761123a8861121c838a612023565b518b518093819263890db72f60e01b83528783019190602083019252565b0381875afa908115610f4057899161129a575b506101008101516001600160a01b03868116911614611270575b50600101611205565b86611293916112826001949989612023565b5261128d8188612023565b5061263e565b9590611267565b6112ae91503d808b833e6111e4818361048d565b8a61124d565b604051806103a0878261106b565b6112df9195503d8088833e6112d7818361048d565b8101906124a1565b933861113d565b346103f15760003660031901126103f15760206040517f00000000000000000000000000000000000000000000000000000000000f42408152f35b346103f15760003660031901126103f1576003546113499033906001600160a01b0316612d1e565b611351612fde565b6000805160206133cf833981519152600160ff198254161790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b801515036103f157565b60a4359061041482611397565b600211156103f157565b60c43590610414826113ae565b346103f15760e03660031901126103f1576004356001600160401b038082116103f157366023830112156103f15781600401359081116103f15736602482840101116103f1576109f091611417610407565b91611420610416565b916114296113a1565b926114326113b8565b946084359360246064359401612921565b346103f1576000806003193601126103ee5760025481805b828110611475575050604080519182526020820192909252f35b60008051602061338f8339815191528101546001600160a01b031682526001602052604082206005015460ff166114af575b60010161145b565b926114bb60019161263e565b9390506114a7565b346103f15760e03660031901126103f15760048035906114e2826103f6565b60c03660231901126103f157600354611505906001600160a01b03163390612d1e565b6001600160a01b03828116600090815260016020526040902060028101805483161561165157611533612b81565b61162e575b611540612b8d565b6115f8575b906115ce61158f7f6b66f5213e80ab64c9628cb4f24a684abc4409cb22961c75f9f2dd13c7b1102b9493611577612b99565b6115d3575b426007850155546001600160a01b031690565b916115a7600560038301549783015492015460ff1690565b90846040519586951698169684919260409194936060840195845260208401521515910152565b0390a3005b6115f36115de612ba5565b600586019060ff801983541691151516179055565b61157c565b60443580158015611622575b6116115784830155611545565b604051632f2a24a960e11b81528590fd5b50620f42408111611604565b6024358015611641576003830155611538565b60405162bfc92160e01b81528590fd5b5050604051632777a68f60e11b81526001600160a01b039093169183019182525081906020010390fd5b346103f15760203660031901126103f157600435611698816103f6565b6003546116b0906001600160a01b03165b3390612ece565b6001600160a01b038181166000908152600160205260409020600292919081906116e59085905b01546001600160a01b031690565b16156117f75761170e60026116d784959460018060a01b03166000526001602052604060002090565b8184169360005b8454808210156117d157868561174261172d85611ff9565b905460039190911b1c6001600160a01b031690565b16146117515750600101611715565b6117a8939495506117a3929161177d61177761172d61177261179b95612bb1565b611ff9565b91611ff9565b90919060018060a01b038084549260031b9316831b921b1916179055565b610423612bdd565b612c5a565b16907f9bc65a9fbc48dd0365f46991a7c615f1330a701313f1bf573dfbbdd48dad48c6600080a3005b50506001600160a01b03166000908152600160205260409020919250906117a890612c5a565b604051632777a68f60e11b81526001600160a01b0383166004820152602490fd5b9060206102e792818152019061020c565b346103f15760003660031901126103f15760405160408101908082106001600160401b038311176104ae576103a09160405260058152640352e302e360dc1b602082015260405191829160208352602083019061020c565b346103f15760003660031901126103f1576003546040516001600160a01b039091168152602090f35b346103f15760803660031901126103f15760048035906118c9826103f6565b6024356118d5816103f6565b604435926118e2846113ae565b6064356118ed612fde565b6001600160a01b039482861615611bb4578115611ba35761190d83612305565b958616928315611b7c576001600160a01b038116600090815260016020526040902096611941610ca460058a015460ff1690565b8015611b5b575b611b345750600160009261195b81610231565b03611aa4575050604080516308c9682b60e31b81526001600160a01b0385168682019081529196916020908290819083010381875afa908115610f4057600091611a85575b5015611a60578551631d7d882b60e21b81526001600160a01b038516868201908152909387918591908290819060200103915afa948515610f40576103a096611a0896610d5b95600092600092611a3f575b505015611a1857606490045b915b015491613009565b6040519081529081906020820190565b507f00000000000000000000000000000000000000000000000000000000000f42406119fe565b611a59935080919250903d10610f3957610f29818361048d565b38806119f2565b8551632777a68f60e11b81526001600160a01b03851681870190815281906020010390fd5b611a9e915060203d602011610f9357610f85818361048d565b386119a0565b60408051631d7d882b60e21b81526001600160a01b039092168783019081529197929490918891908290819060200103915afa948515610f40576103a096611a089685610d5b96928192611b10575b505015611b0557606490045b91611a00565b506003820154611aff565b909250611b2c915060403d604011610f3957610f29818361048d565b909138611af3565b60405163039c0b3360e11b81526001600160a01b0390911681880190815281906020010390fd5b5060028801548590611b75906001600160a01b0316610cc6565b1415611948565b604051632777a68f60e11b81526001600160a01b0390911681870190815281906020010390fd5b60405163162908e360e11b81528590fd5b604051634726455360e11b81526001600160a01b03841681870190815281906020010390fd5b346103f15760203660031901126103f157600435611bf7816103f6565b60018060a01b03806003541691604051632474521560e21b81526020816044816000978860048301523360248301525afa908115610f40578491611ce7575b5015611c9257168015611c7a5781546001600160a01b031916811782557f7aed1d3e8155a07ccf395e44ea3109a0e2d6c9b29bbbe9f142d9790596f4dc808280a280f35b60249060405190634726455360e11b82526004820152fd5b6040516d026b4b9b9b4b733903937b6329d160951b60208201526000602e8201526109cb90611cce81604e81015b03601f19810183528261048d565b60405163973d02cb60e01b815291829160048301611818565b611d00915060203d602011610f9357610f85818361048d565b38611c36565b346103f1576000806003193601126103ee576002548190825b818110611dd35750611d39611d3383612cec565b92611f93565b92805b828110611d55575050506103a0604051928392836102ea565b611d6161172d82611ff9565b6001600160a01b0381166000908152600160205260409020611d89906005905b015460ff1690565b611d97575b50600101611d3c565b82611dc2610c8e83610423611dcc95611db3600198998c612023565b6001600160a01b039091169052565b6112828289612023565b9190611d8e565b611de76005611d8161042361172d85611ff9565b611df4575b600101611d1f565b91611e0060019161263e565b929050611dec565b9060206102e792818152019061025e565b346103f15760203660031901126103f157600435611e36816103f6565b611e3e611f3c565b506001600160a01b031660009081526001602052604090206103a090611ef0611ee66008611e6a610854565b93611e74816104b3565b855260018101546001600160a01b0316602086015260028101546001600160a01b031660408601526003810154606086015260048101546080860152611eca611ec1600583015460ff1690565b151560a0870152565b600681015460c0860152600781015460e0860152015460ff1690565b6101008301612037565b60405191829182611e08565b346103f15760003660031901126103f1576000546040516001600160a01b039091168152602090f35b6001600160401b0381116104ae5760051b60200190565b6040519061012082018281106001600160401b038211176104ae5760405281606081526101006000918260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201520152565b90611f9d82611f25565b611faa604051918261048d565b8281528092611fbb601f1991611f25565b019060005b828110611fcc57505050565b602090611fd7611f3c565b82828501015201611fc0565b634e487b7160e01b600052603260045260246000fd5b60025481101561201e57600260005260008051602061338f8339815191520190600090565b611fe3565b805182101561201e5760209160051b010190565b600282101561023b5752565b906104146120d06008612054610854565b9461205e816104b3565b865260018101546001600160a01b0316602087015260028101546001600160a01b0316604087015260038101546060870152600481015460808701526120b46120ab600583015460ff1690565b151560a0880152565b600681015460c0870152600781015460e0870152015460ff1690565b6101008401612037565b60405190600254808352826020916020820190600260005260008051602061338f833981519152936000905b82821061211c575050506104149250038361048d565b85546001600160a01b031684526001958601958895509381019390910190612106565b5190610414826103f6565b908160209103126103f157516102e7816103f6565b6040513d6000823e3d90fd5b90612174613213565b61217c612fa6565b6001600160a01b038281169290919083156122e25750818116156122e257600080546001600160a01b0319166001600160a01b0392909216919091179055604051631c2d8fb360e31b8082527f30cbe54a1d58dd2abf9f68ee5d9ee9f65e3c220ce3b6a5020ffb1f6a7a642426600483015260209391908482602481865afa8015610f40578461222f9187946000916122c5575b501660018060a01b03166001600160601b0360a01b6003541617600355565b6040519081527f19005857dd029bd1a5a4124a299205774a4a07320746a7b8f15c072094abd909600482015291829060249082905afa908115610f405761041493600092612298575b50501660018060a01b03166001600160601b0360a01b6004541617600455565b6122b79250803d106122be575b6122af818361048d565b81019061214a565b3880612278565b503d6122a5565b6122dc9150853d87116122be576122af818361048d565b38612210565b604051634726455360e11b81526001600160a01b03919091166004820152602490fd5b6001600160a01b031660009081526001602052604090206123b2610ca461232a610854565b92612334816104b3565b845260018101546001600160a01b0316602085015260028101546123ac906001600160a01b03166001600160a01b0316604086019081529460038301546060820152600483015460808201526101006123a56008612396600587015460ff1690565b151560a0850190815295611eca565b9101612037565b51151590565b6123c357516001600160a01b031690565b60405163169652d560e01b8152600490fd5b6040519061016082018281106001600160401b038211176104ae57604052816101406000918281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201528261010082015260606101208201520152565b91908260409103126103f157602082519201516102e781611397565b908160209103126103f157516102e781611397565b634e487b7160e01b600052601160045260246000fd5b811561248b570490565b634e487b7160e01b600052601260045260246000fd5b60209081818403126103f1578051906001600160401b0382116103f157019180601f840112156103f15782516124d681611f25565b936124e4604051958661048d565b818552838086019260051b8201019283116103f1578301905b82821061250b575050505090565b815181529083019083016124fd565b81601f820112156103f157805161253081610894565b9261253e604051948561048d565b818452602082840101116103f1576102e791602080850191016101e9565b5190610414826113ae565b906020828203126103f15781516001600160401b03928382116103f1570190610160828203126103f157612599610834565b926125a38361213f565b84526125b16020840161213f565b60208501526125c26040840161213f565b6040850152606083015160608501526080830151608085015260a083015160a085015260c083015160c085015260e083015160e085015261010061260781850161213f565b9085015261012091828401519182116103f15761262591840161251a565b9083015261263761014080920161255c565b9082015290565b600019811461264d5760010190565b61246b565b9061265c82611f25565b612669604051918261048d565b828152809261267a601f1991611f25565b019060005b82811061268b57505050565b6020906126966123d5565b8282850101520161267f565b8181106126ad575050565b600081556001016126a2565b9190601f81116126c857505050565b610414926000526020600020906020601f840160051c830193106126f4575b601f0160051c01906126a2565b90915081906126e7565b91909182516001600160401b0381116104ae576127258161271f845461043d565b846126b9565b602080601f83116001146127685750819061275993949560009261275d575b50508160011b916000199060031b1c19161790565b9055565b015190503880612744565b90601f1983169561277e85600052602060002090565b926000905b8882106127bb575050836001959697106127a2575b505050811b019055565b015160001960f88460031b161c19169055388080612798565b80600185968294968601518155019501930190612783565b90600281101561023b5760ff80198354169116179055565b6008610100610414936127ff8151856126fe565b60208101516001850180546001600160a01b039283166001600160a01b0319918216179091556040830151600287018054919093169116179055606081015160038501556080810151600485015560a081015161285d9015156115de565b60c0810151600685015560e0810151600785015501519161287d83610231565b016127d3565b60025490600160401b8210156104ae57600182018060025582101561201e57600260005260008051602061338f83398151915290910180546001600160a01b0319166001600160a01b03909216919091179055565b919360c085608095999896610414989460a087528160a0880152838701376000828287010152601f80199101168401019760208401526040830152151560608201520190610251565b9396929695919594909461293f6116a960035460018060a01b031690565b8515612b42576001600160a01b0387811697908815612b215789169889156122e2578215612b105783158015612b04575b612af257612998610cc660026116d78560018060a01b03166000526001602052604060002090565b151580612ac5575b612a775791612a6687969492612a618a612a0f612a7299976129ee7f510bd620ef43b4190dab7351704d501c208abac108d2d02ce189e0510c6b0a4a9e9d6129e6610854565b9436916108af565b83526001600160a01b03851660208401526001600160a01b03166040830152565b846060820152856080820152612a2a8760a083019015159052565b4260c08201524260e0820152612a44886101008301612037565b6001600160a01b03831660009081526001602052604090206127eb565b612883565b604051968796876128d8565b0390a3565b506001600160a01b0381166000908152600160205260409020612a9c906002906116d7565b604051637113ace960e01b81526001600160a01b03928316600482015291166024820152604490fd5b5089612aeb610cc660026116d78660018060a01b03166000526001602052604060002090565b14156129a0565b604051632f2a24a960e11b8152600490fd5b50620f42408411612970565b60405162bfc92160e01b8152600490fd5b604051634726455360e11b81526001600160a01b0383166004820152602490fd5b60405163dd23c3ad60e01b8152602060048201526016602482015275456d70747920696e746567726174696f6e207479706560501b6044820152606490fd5b6084356102e781611397565b60a4356102e781611397565b60c4356102e781611397565b6064356102e781611397565b60001981019190821161264d57565b600603906006821161264d57565b60051981019190821161264d57565b6002548015612c31576000198101908082101561201e577f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acd906002600052016001600160601b0360a01b8154169055600255565b634e487b7160e01b600052603160045260246000fd5b8181029291811591840414171561264d57565b612c64815461043d565b80612c9e575b5060086000918260018201558260028201558260038201558260048201558260058201558260068201558260078201550155565b601f8111600114612cb55750600081555b38612c6a565b612cda906001601f612ccc85600052602060002090565b920160051c820191016126a2565b60008181526020812081835555612caf565b90612cf682611f25565b612d03604051918261048d565b8281528092612d14601f1991611f25565b0190602036910137565b604051632474521560e21b81527f7e1a33dfd0e7a15131be76fc7e3c5b60960f01694bdee46a5c1fc1788fe9e3b960048201526001600160a01b0392831660248201529160209183916044918391165afa908115610f4057600091612dd7575b5015612d8657565b6040516d026b4b9b9b4b733903937b6329d160951b60208201527f7e1a33dfd0e7a15131be76fc7e3c5b60960f01694bdee46a5c1fc1788fe9e3b9602e8201526109cb90611cce81604e8101611cc0565b612df0915060203d602011610f9357610f85818361048d565b38612d7e565b604051632474521560e21b81527f189ab7a9244df0848122154315af71fe140f3db0fe014031783b0946b8c9d2e360048201526001600160a01b0392831660248201529160209183916044918391165afa908115610f4057600091612eaf575b5015612e5e57565b6040516d026b4b9b9b4b733903937b6329d160951b60208201527f189ab7a9244df0848122154315af71fe140f3db0fe014031783b0946b8c9d2e3602e8201526109cb90611cce81604e8101611cc0565b612ec8915060203d602011610f9357610f85818361048d565b38612e56565b604051632474521560e21b81527f7edcee67725a77bfa311b39349d7e96df9b23fbdbdcb328dfc17d77926920c1360048201526001600160a01b0392831660248201529160209183916044918391165afa908115610f4057600091612f87575b5015612f3657565b6040516d026b4b9b9b4b733903937b6329d160951b60208201527f7edcee67725a77bfa311b39349d7e96df9b23fbdbdcb328dfc17d77926920c13602e8201526109cb90611cce81604e8101611cc0565b612fa0915060203d602011610f9357610f85818361048d565b38612f2e565b612fae613213565b612fb6613213565b6000805160206133cf833981519152805460ff19169055565b908160209103126103f1575190565b60ff6000805160206133cf8339815191525416612ff757565b60405163d93c066560e01b8152600490fd5b9190808302928304036103f157620f424091020490565b908160209103126103f1575160ff811681036103f15790565b60ff60069116019060ff821161264d57565b90601381101561201e5760051b0190565b60405163313ce56760e01b81529091602090829060049082906001600160a01b03165afa908115610f40576000916131e4575b5061317561316f61309e610874565b6001815292600a6020850152606460408501526103e860608501526127106080850152620186a060a0850152620f424060c08501526298968060e08501526305f5e100610100850152633b9aca006101208501526402540be40061014085015264174876e80061016085015264e8d4a510006101808501526509184e72a0006101a0850152655af3107a40006101c085015266038d7ea4c680006101e0850152662386f26fc1000061020085015267016345785d8a0000610220850152670de0b6b3a7640000610240850152613039565b60ff1690565b60068111156131ba576131a861319b6102e794936131956131b494612bce565b9061304b565b516001600160401b031690565b6001600160401b031690565b90612481565b600681106131c757505090565b6131a861319b6102e794936131956131de94612bc0565b90612c47565b613206915060203d60201161320c575b6131fe818361048d565b810190613020565b3861308f565b503d6131f4565b60ff6000805160206133ef8339815191525460401c161561323057565b604051631afcd79f60e31b8152600490fd5b90813b156132c8576000805160206133af83398151915280546001600160a01b0319166001600160a01b0384169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a28051156132ad576132aa916132e9565b50565b5050346132b657565b60405163b398979f60e01b8152600490fd5b604051634c9c8ce360e01b81526001600160a01b0383166004820152602490fd5b6000806102e793602081519101845af43d15613327573d9161330a83610894565b92613318604051948561048d565b83523d6000602085013e61332b565b6060915b90613352575080511561334057805190602001fd5b60405163d6bda27560e01b8152600490fd5b81511580613385575b613363575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b1561335b56fe405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbccd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212200ae85bbb59bcde699351b8945079c40c798bd54e3ccded63d90798899944f93f64736f6c63430008170033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"paris","libraries":{},"optimizer":{"enabled":true,"runs":200},"outputSelection":{"*":{"":["*"],"*":["*"]}},"viaIR":true},"optimization_runs":200,"sourcify_repo_url":null,"decoded_constructor_args":null,"compiler_version":"v0.8.23+commit.f704f362","is_verified_via_verifier_alliance":false,"verified_at":"2026-05-04T02:24:13.367127Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x60c080604052346100485730608052620f424060a052613444908161004e82396080518181816109390152610a7f015260a051818181610eea015281816112fe0152611a1b0152f35b600080fdfe6080604052600436101561001257600080fd5b60003560e01c8063191614e1146101a757806338df2ff3146101a25780633f4ba83a1461019d578063485cc955146101985780634cd36c66146101935780634f1ef2861461018e57806352d1902d1461018957806357453d06146101845780635c975abb1461017f578063618c373e1461017a57806367e3c4d4146101755780636fb07afc146101705780637fcf21561461016b5780638456cb591461016657806387fe819b1461016157806395f9e2d21461015c578063a878fa9014610157578063ac848eab14610152578063ad3cb1cc1461014d578063bc43cbaf14610148578063c08dc8fd14610143578063c0d786551461013e578063c74b031d14610139578063ee747f1d146101345763f887ea401461012f57600080fd5b611efc565b611e19565b611d06565b611bda565b6118aa565b611881565b611829565b61167b565b6114c3565b611443565b6113c5565b611321565b6112e6565b6110cf565b611042565b610bfa565b610b10565b610ad7565b610a6c565b6108e6565b610804565b6106e2565b610637565b6105b2565b610360565b90815180825260208080930193019160005b8281106101cc575050505090565b83516001600160a01b0316855293810193928101926001016101be565b60005b8381106101fc5750506000910152565b81810151838201526020016101ec565b90602091610225815180928185528580860191016101e9565b601f01601f1916010190565b6002111561023b57565b634e487b7160e01b600052602160045260246000fd5b90600282101561023b5752565b906102e79061027761012084519080845283019061020c565b6020808501516001600160a01b0390811691840191909152604080860151909116908301529260608101516060830152608081015160808301526102c460a082015160a084019015159052565b60c081015160c083015260e081015160e083015261010080910151910190610251565b90565b906102fd906040835260408301906101ac565b90602090818184039101528251908183528083019281808460051b8301019501936000915b8483106103325750505050505090565b9091929394958480610350600193601f198682030187528a5161025e565b9801930193019194939290610322565b346103f1576000806003193601126103ee5760025461037e81611f93565b91805b8281106103a457836103916120da565b6103a0604051928392836102ea565b0390f35b600190818060a01b038160008051602061338f8339815191520154168352816020526103d260408420612043565b6103dc8287612023565b526103e78186612023565b5001610381565b80fd5b600080fd5b6001600160a01b038116036103f157565b60243590610414826103f6565b565b60443590610414826103f6565b6001600160a01b0316600090815260016020526040902090565b90600182811c9216801561046d575b602083101461045757565b634e487b7160e01b600052602260045260246000fd5b91607f169161044c565b634e487b7160e01b600052604160045260246000fd5b90601f801991011681019081106001600160401b038211176104ae57604052565b610477565b906040519182600082546104c68161043d565b9081845260209460019160018116908160001461053457506001146104f5575b5050506104149250038361048d565b600090815285812095935091905b81831061051c57505061041493508201013880806104e6565b85548884018501529485019487945091830191610503565b9250505061041494925060ff191682840152151560051b8201013880806104e6565b94909361010096926105796104149a969c9b99959c610120808a5289019061020c565b6001600160a01b0391821660208901529b16604087015260608601526080850152151560a084015260c083015260e08201520190610251565b346103f15760203660031901126103f1576004356105cf816103f6565b6001600160a01b0390811660009081526001602052604090206103a06105f4826104b3565b918360018201541693600282015416906003810154600482015460ff6005840154169060068401549260ff600860078701549601541695604051998a998a610556565b346103f15760003660031901126103f15760035461065f9033906001600160a01b0316612d1e565b6000805160206133cf833981519152805460ff8116156106ab5760ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b604051638dfc202b60e01b8152600490fd5b60409060031901126103f1576004356106d5816103f6565b906024356102e7816103f6565b346103f1576106f0366106bd565b906000805160206133ef83398151915254916001600160401b0360ff8460401c16159316801590816107fc575b60011490816107f2575b1590816107e9575b506107d7576000805160206133ef833981519152805467ffffffffffffffff1916600117905561076391836107b25761216b565b61076957005b6000805160206133ef833981519152805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b6000805160206133ef833981519152805460ff60401b1916600160401b17905561216b565b60405163f92ee8a960e01b8152600490fd5b9050153861072f565b303b159150610727565b84915061071d565b346103f15760003660031901126103f1576103a06108206120da565b6040519182916020835260208301906101ac565b6040519061016082018281106001600160401b038211176104ae57604052565b6040519061012082018281106001600160401b038211176104ae57604052565b6040519061026082018281106001600160401b038211176104ae57604052565b6001600160401b0381116104ae57601f01601f191660200190565b9291926108bb82610894565b916108c9604051938461048d565b8294818452818301116103f1578281602093846000960137010152565b60403660031901126103f1576004803590610900826103f6565b6024356001600160401b0381116103f157366023820112156103f15761092f90369060248185013591016108af565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116308114908115610a50575b50610a3f579060208261097e8594600354163390612df6565b6040516352d1902d60e01b8152938491829088165afa60009281610a0e575b506109cf575050604051634c9c8ce360e01b81526001600160a01b0390921690820190815281906020010390fd5b0390fd5b83836000805160206133af83398151915284036109f2576109f08383613242565b005b604051632a87526960e21b815290810184815281906020010390fd5b610a3191935060203d602011610a38575b610a29818361048d565b810190612fcf565b913861099d565b503d610a1f565b60405163703e46dd60e11b81528390fd5b9050816000805160206133af8339815191525416141538610965565b346103f15760003660031901126103f1577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163003610ac55760206040516000805160206133af8339815191528152f35b60405163703e46dd60e11b8152600490fd5b346103f15760203660031901126103f1576020610afe600435610af9816103f6565b612305565b6040516001600160a01b039091168152f35b346103f15760003660031901126103f157602060ff6000805160206133cf83398151915254166040519015158152f35b80516001600160a01b03168252906102e790610bd96101606020858101516001600160a01b0316908401526040858101516001600160a01b031690840152606085810151908401526080808601519084015260a0808601519084015260c0808601519084015260e08086015190840152610100808601516001600160a01b0316908401526101209080828701519285015283019061020c565b9261014080910151910190610251565b9060206102e7928181520190610b40565b346103f15760a03660031901126103f1576004803590610c19826103f6565b60243590610c26826103f6565b60443591610c33836103f6565b606435610c3e6123d5565b50600080549093906001600160a01b03908116330361102b57610c5f612fde565b821561101b5780871615610ff5576001600160a01b0384166000908152600160205260409020610c9390612043565b612043565b92610ca8610ca460a0860151151590565b1590565b610fe45760409687850192610cd2610cc6855160018060a01b031690565b6001600160a01b031690565b15610fbf5783518790610cef90610cc6906001600160a01b031681565b8a51631d7d882b60e21b8082526001600160a01b039093168189019081529097918c918991908290819060200103915afa928315610f40578a978b94610f9a575b50848116908a1603610dff57505015610dee57610d6081610d5b606487045b60808901519086613009565b61305c565b92516001600160a01b0316945195610d76610834565b6001600160a01b03909a168a526001600160a01b031660208a01526001600160a01b031688880152606088015260808701524260a087015260843560c08701526064900460e08601526001600160a01b0316610100850152610120840152610de2906101408401612037565b516103a0819282610be9565b610d6081610d5b6060880151610d4f565b909150610e4c602084610e21610cc6610cc68a9e989e5160018060a01b031690565b8d516308c9682b60e31b81526001600160a01b03909216858301908152919384928391829160200190565b03915afa908115610f40578491610f6b575b5015610f45578451610ea893928b928b92610e8390610cc6906001600160a01b031681565b84519283526001600160a01b0390931690820190815290948592918391829160200190565b03915afa908115610f405780928192610f0e575b505015610ee4576064610ed791045b60808601519083613009565b95610d608160019861305c565b50610ed77f0000000000000000000000000000000000000000000000000000000000000000610ecb565b909250610f319150893d8b11610f39575b610f29818361048d565b81019061243a565b909138610ebc565b503d610f1f565b61215f565b8951632777a68f60e11b81526001600160a01b038a169181019182529081906020010390fd5b610f8d915060203d602011610f93575b610f85818361048d565b810190612456565b38610e5e565b503d610f7b565b909350610fb59197508b3d8d11610f3957610f29818361048d565b9690969238610d30565b8851632777a68f60e11b81526001600160a01b03881681870190815281906020010390fd5b60405163169652d560e01b81528390fd5b604051634726455360e11b81526001600160a01b03881681840190815281906020010390fd5b5060405163162908e360e11b8152fd5b6040516305f112b360e41b81523381840152602490fd5b346103f15760003660031901126103f1576004546040516001600160a01b039091168152602090f35b6020808201906020835283518092526040830192602060408460051b8301019501936000915b8483106110a15750505050505090565b90919293949584806110bf600193603f198682030187528a51610b40565b9801930193019194939290611091565b346103f15761112a6110e0366106bd565b600480549091906110f9906001600160a01b0316610cc6565b604080516340398d6760e01b81526001600160a01b0390951660048601526000959091908690869081906024820190565b0381845afa948515610f405786956112c2575b508593865b86518110156111f25761117788611159838a612023565b5186518093819263890db72f60e01b83528783019190602083019252565b0381875afa908115610f40576111a191610100918b916111d0575b5001516001600160a01b031690565b6001600160a01b038681169116146111bc575b600101611142565b946111c860019161263e565b9590506111b4565b6111ec91503d808d833e6111e4818361048d565b810190612567565b38611192565b509194926112008795612652565b918593865b86518110156112b45761123a8861121c838a612023565b518b518093819263890db72f60e01b83528783019190602083019252565b0381875afa908115610f4057899161129a575b506101008101516001600160a01b03868116911614611270575b50600101611205565b86611293916112826001949989612023565b5261128d8188612023565b5061263e565b9590611267565b6112ae91503d808b833e6111e4818361048d565b8a61124d565b604051806103a0878261106b565b6112df9195503d8088833e6112d7818361048d565b8101906124a1565b933861113d565b346103f15760003660031901126103f15760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346103f15760003660031901126103f1576003546113499033906001600160a01b0316612d1e565b611351612fde565b6000805160206133cf833981519152600160ff198254161790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b801515036103f157565b60a4359061041482611397565b600211156103f157565b60c43590610414826113ae565b346103f15760e03660031901126103f1576004356001600160401b038082116103f157366023830112156103f15781600401359081116103f15736602482840101116103f1576109f091611417610407565b91611420610416565b916114296113a1565b926114326113b8565b946084359360246064359401612921565b346103f1576000806003193601126103ee5760025481805b828110611475575050604080519182526020820192909252f35b60008051602061338f8339815191528101546001600160a01b031682526001602052604082206005015460ff166114af575b60010161145b565b926114bb60019161263e565b9390506114a7565b346103f15760e03660031901126103f15760048035906114e2826103f6565b60c03660231901126103f157600354611505906001600160a01b03163390612d1e565b6001600160a01b03828116600090815260016020526040902060028101805483161561165157611533612b81565b61162e575b611540612b8d565b6115f8575b906115ce61158f7f6b66f5213e80ab64c9628cb4f24a684abc4409cb22961c75f9f2dd13c7b1102b9493611577612b99565b6115d3575b426007850155546001600160a01b031690565b916115a7600560038301549783015492015460ff1690565b90846040519586951698169684919260409194936060840195845260208401521515910152565b0390a3005b6115f36115de612ba5565b600586019060ff801983541691151516179055565b61157c565b60443580158015611622575b6116115784830155611545565b604051632f2a24a960e11b81528590fd5b50620f42408111611604565b6024358015611641576003830155611538565b60405162bfc92160e01b81528590fd5b5050604051632777a68f60e11b81526001600160a01b039093169183019182525081906020010390fd5b346103f15760203660031901126103f157600435611698816103f6565b6003546116b0906001600160a01b03165b3390612ece565b6001600160a01b038181166000908152600160205260409020600292919081906116e59085905b01546001600160a01b031690565b16156117f75761170e60026116d784959460018060a01b03166000526001602052604060002090565b8184169360005b8454808210156117d157868561174261172d85611ff9565b905460039190911b1c6001600160a01b031690565b16146117515750600101611715565b6117a8939495506117a3929161177d61177761172d61177261179b95612bb1565b611ff9565b91611ff9565b90919060018060a01b038084549260031b9316831b921b1916179055565b610423612bdd565b612c5a565b16907f9bc65a9fbc48dd0365f46991a7c615f1330a701313f1bf573dfbbdd48dad48c6600080a3005b50506001600160a01b03166000908152600160205260409020919250906117a890612c5a565b604051632777a68f60e11b81526001600160a01b0383166004820152602490fd5b9060206102e792818152019061020c565b346103f15760003660031901126103f15760405160408101908082106001600160401b038311176104ae576103a09160405260058152640352e302e360dc1b602082015260405191829160208352602083019061020c565b346103f15760003660031901126103f1576003546040516001600160a01b039091168152602090f35b346103f15760803660031901126103f15760048035906118c9826103f6565b6024356118d5816103f6565b604435926118e2846113ae565b6064356118ed612fde565b6001600160a01b039482861615611bb4578115611ba35761190d83612305565b958616928315611b7c576001600160a01b038116600090815260016020526040902096611941610ca460058a015460ff1690565b8015611b5b575b611b345750600160009261195b81610231565b03611aa4575050604080516308c9682b60e31b81526001600160a01b0385168682019081529196916020908290819083010381875afa908115610f4057600091611a85575b5015611a60578551631d7d882b60e21b81526001600160a01b038516868201908152909387918591908290819060200103915afa948515610f40576103a096611a0896610d5b95600092600092611a3f575b505015611a1857606490045b915b015491613009565b6040519081529081906020820190565b507f00000000000000000000000000000000000000000000000000000000000000006119fe565b611a59935080919250903d10610f3957610f29818361048d565b38806119f2565b8551632777a68f60e11b81526001600160a01b03851681870190815281906020010390fd5b611a9e915060203d602011610f9357610f85818361048d565b386119a0565b60408051631d7d882b60e21b81526001600160a01b039092168783019081529197929490918891908290819060200103915afa948515610f40576103a096611a089685610d5b96928192611b10575b505015611b0557606490045b91611a00565b506003820154611aff565b909250611b2c915060403d604011610f3957610f29818361048d565b909138611af3565b60405163039c0b3360e11b81526001600160a01b0390911681880190815281906020010390fd5b5060028801548590611b75906001600160a01b0316610cc6565b1415611948565b604051632777a68f60e11b81526001600160a01b0390911681870190815281906020010390fd5b60405163162908e360e11b81528590fd5b604051634726455360e11b81526001600160a01b03841681870190815281906020010390fd5b346103f15760203660031901126103f157600435611bf7816103f6565b60018060a01b03806003541691604051632474521560e21b81526020816044816000978860048301523360248301525afa908115610f40578491611ce7575b5015611c9257168015611c7a5781546001600160a01b031916811782557f7aed1d3e8155a07ccf395e44ea3109a0e2d6c9b29bbbe9f142d9790596f4dc808280a280f35b60249060405190634726455360e11b82526004820152fd5b6040516d026b4b9b9b4b733903937b6329d160951b60208201526000602e8201526109cb90611cce81604e81015b03601f19810183528261048d565b60405163973d02cb60e01b815291829160048301611818565b611d00915060203d602011610f9357610f85818361048d565b38611c36565b346103f1576000806003193601126103ee576002548190825b818110611dd35750611d39611d3383612cec565b92611f93565b92805b828110611d55575050506103a0604051928392836102ea565b611d6161172d82611ff9565b6001600160a01b0381166000908152600160205260409020611d89906005905b015460ff1690565b611d97575b50600101611d3c565b82611dc2610c8e83610423611dcc95611db3600198998c612023565b6001600160a01b039091169052565b6112828289612023565b9190611d8e565b611de76005611d8161042361172d85611ff9565b611df4575b600101611d1f565b91611e0060019161263e565b929050611dec565b9060206102e792818152019061025e565b346103f15760203660031901126103f157600435611e36816103f6565b611e3e611f3c565b506001600160a01b031660009081526001602052604090206103a090611ef0611ee66008611e6a610854565b93611e74816104b3565b855260018101546001600160a01b0316602086015260028101546001600160a01b031660408601526003810154606086015260048101546080860152611eca611ec1600583015460ff1690565b151560a0870152565b600681015460c0860152600781015460e0860152015460ff1690565b6101008301612037565b60405191829182611e08565b346103f15760003660031901126103f1576000546040516001600160a01b039091168152602090f35b6001600160401b0381116104ae5760051b60200190565b6040519061012082018281106001600160401b038211176104ae5760405281606081526101006000918260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201520152565b90611f9d82611f25565b611faa604051918261048d565b8281528092611fbb601f1991611f25565b019060005b828110611fcc57505050565b602090611fd7611f3c565b82828501015201611fc0565b634e487b7160e01b600052603260045260246000fd5b60025481101561201e57600260005260008051602061338f8339815191520190600090565b611fe3565b805182101561201e5760209160051b010190565b600282101561023b5752565b906104146120d06008612054610854565b9461205e816104b3565b865260018101546001600160a01b0316602087015260028101546001600160a01b0316604087015260038101546060870152600481015460808701526120b46120ab600583015460ff1690565b151560a0880152565b600681015460c0870152600781015460e0870152015460ff1690565b6101008401612037565b60405190600254808352826020916020820190600260005260008051602061338f833981519152936000905b82821061211c575050506104149250038361048d565b85546001600160a01b031684526001958601958895509381019390910190612106565b5190610414826103f6565b908160209103126103f157516102e7816103f6565b6040513d6000823e3d90fd5b90612174613213565b61217c612fa6565b6001600160a01b038281169290919083156122e25750818116156122e257600080546001600160a01b0319166001600160a01b0392909216919091179055604051631c2d8fb360e31b8082527f30cbe54a1d58dd2abf9f68ee5d9ee9f65e3c220ce3b6a5020ffb1f6a7a642426600483015260209391908482602481865afa8015610f40578461222f9187946000916122c5575b501660018060a01b03166001600160601b0360a01b6003541617600355565b6040519081527f19005857dd029bd1a5a4124a299205774a4a07320746a7b8f15c072094abd909600482015291829060249082905afa908115610f405761041493600092612298575b50501660018060a01b03166001600160601b0360a01b6004541617600455565b6122b79250803d106122be575b6122af818361048d565b81019061214a565b3880612278565b503d6122a5565b6122dc9150853d87116122be576122af818361048d565b38612210565b604051634726455360e11b81526001600160a01b03919091166004820152602490fd5b6001600160a01b031660009081526001602052604090206123b2610ca461232a610854565b92612334816104b3565b845260018101546001600160a01b0316602085015260028101546123ac906001600160a01b03166001600160a01b0316604086019081529460038301546060820152600483015460808201526101006123a56008612396600587015460ff1690565b151560a0850190815295611eca565b9101612037565b51151590565b6123c357516001600160a01b031690565b60405163169652d560e01b8152600490fd5b6040519061016082018281106001600160401b038211176104ae57604052816101406000918281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201528261010082015260606101208201520152565b91908260409103126103f157602082519201516102e781611397565b908160209103126103f157516102e781611397565b634e487b7160e01b600052601160045260246000fd5b811561248b570490565b634e487b7160e01b600052601260045260246000fd5b60209081818403126103f1578051906001600160401b0382116103f157019180601f840112156103f15782516124d681611f25565b936124e4604051958661048d565b818552838086019260051b8201019283116103f1578301905b82821061250b575050505090565b815181529083019083016124fd565b81601f820112156103f157805161253081610894565b9261253e604051948561048d565b818452602082840101116103f1576102e791602080850191016101e9565b5190610414826113ae565b906020828203126103f15781516001600160401b03928382116103f1570190610160828203126103f157612599610834565b926125a38361213f565b84526125b16020840161213f565b60208501526125c26040840161213f565b6040850152606083015160608501526080830151608085015260a083015160a085015260c083015160c085015260e083015160e085015261010061260781850161213f565b9085015261012091828401519182116103f15761262591840161251a565b9083015261263761014080920161255c565b9082015290565b600019811461264d5760010190565b61246b565b9061265c82611f25565b612669604051918261048d565b828152809261267a601f1991611f25565b019060005b82811061268b57505050565b6020906126966123d5565b8282850101520161267f565b8181106126ad575050565b600081556001016126a2565b9190601f81116126c857505050565b610414926000526020600020906020601f840160051c830193106126f4575b601f0160051c01906126a2565b90915081906126e7565b91909182516001600160401b0381116104ae576127258161271f845461043d565b846126b9565b602080601f83116001146127685750819061275993949560009261275d575b50508160011b916000199060031b1c19161790565b9055565b015190503880612744565b90601f1983169561277e85600052602060002090565b926000905b8882106127bb575050836001959697106127a2575b505050811b019055565b015160001960f88460031b161c19169055388080612798565b80600185968294968601518155019501930190612783565b90600281101561023b5760ff80198354169116179055565b6008610100610414936127ff8151856126fe565b60208101516001850180546001600160a01b039283166001600160a01b0319918216179091556040830151600287018054919093169116179055606081015160038501556080810151600485015560a081015161285d9015156115de565b60c0810151600685015560e0810151600785015501519161287d83610231565b016127d3565b60025490600160401b8210156104ae57600182018060025582101561201e57600260005260008051602061338f83398151915290910180546001600160a01b0319166001600160a01b03909216919091179055565b919360c085608095999896610414989460a087528160a0880152838701376000828287010152601f80199101168401019760208401526040830152151560608201520190610251565b9396929695919594909461293f6116a960035460018060a01b031690565b8515612b42576001600160a01b0387811697908815612b215789169889156122e2578215612b105783158015612b04575b612af257612998610cc660026116d78560018060a01b03166000526001602052604060002090565b151580612ac5575b612a775791612a6687969492612a618a612a0f612a7299976129ee7f510bd620ef43b4190dab7351704d501c208abac108d2d02ce189e0510c6b0a4a9e9d6129e6610854565b9436916108af565b83526001600160a01b03851660208401526001600160a01b03166040830152565b846060820152856080820152612a2a8760a083019015159052565b4260c08201524260e0820152612a44886101008301612037565b6001600160a01b03831660009081526001602052604090206127eb565b612883565b604051968796876128d8565b0390a3565b506001600160a01b0381166000908152600160205260409020612a9c906002906116d7565b604051637113ace960e01b81526001600160a01b03928316600482015291166024820152604490fd5b5089612aeb610cc660026116d78660018060a01b03166000526001602052604060002090565b14156129a0565b604051632f2a24a960e11b8152600490fd5b50620f42408411612970565b60405162bfc92160e01b8152600490fd5b604051634726455360e11b81526001600160a01b0383166004820152602490fd5b60405163dd23c3ad60e01b8152602060048201526016602482015275456d70747920696e746567726174696f6e207479706560501b6044820152606490fd5b6084356102e781611397565b60a4356102e781611397565b60c4356102e781611397565b6064356102e781611397565b60001981019190821161264d57565b600603906006821161264d57565b60051981019190821161264d57565b6002548015612c31576000198101908082101561201e577f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acd906002600052016001600160601b0360a01b8154169055600255565b634e487b7160e01b600052603160045260246000fd5b8181029291811591840414171561264d57565b612c64815461043d565b80612c9e575b5060086000918260018201558260028201558260038201558260048201558260058201558260068201558260078201550155565b601f8111600114612cb55750600081555b38612c6a565b612cda906001601f612ccc85600052602060002090565b920160051c820191016126a2565b60008181526020812081835555612caf565b90612cf682611f25565b612d03604051918261048d565b8281528092612d14601f1991611f25565b0190602036910137565b604051632474521560e21b81527f7e1a33dfd0e7a15131be76fc7e3c5b60960f01694bdee46a5c1fc1788fe9e3b960048201526001600160a01b0392831660248201529160209183916044918391165afa908115610f4057600091612dd7575b5015612d8657565b6040516d026b4b9b9b4b733903937b6329d160951b60208201527f7e1a33dfd0e7a15131be76fc7e3c5b60960f01694bdee46a5c1fc1788fe9e3b9602e8201526109cb90611cce81604e8101611cc0565b612df0915060203d602011610f9357610f85818361048d565b38612d7e565b604051632474521560e21b81527f189ab7a9244df0848122154315af71fe140f3db0fe014031783b0946b8c9d2e360048201526001600160a01b0392831660248201529160209183916044918391165afa908115610f4057600091612eaf575b5015612e5e57565b6040516d026b4b9b9b4b733903937b6329d160951b60208201527f189ab7a9244df0848122154315af71fe140f3db0fe014031783b0946b8c9d2e3602e8201526109cb90611cce81604e8101611cc0565b612ec8915060203d602011610f9357610f85818361048d565b38612e56565b604051632474521560e21b81527f7edcee67725a77bfa311b39349d7e96df9b23fbdbdcb328dfc17d77926920c1360048201526001600160a01b0392831660248201529160209183916044918391165afa908115610f4057600091612f87575b5015612f3657565b6040516d026b4b9b9b4b733903937b6329d160951b60208201527f7edcee67725a77bfa311b39349d7e96df9b23fbdbdcb328dfc17d77926920c13602e8201526109cb90611cce81604e8101611cc0565b612fa0915060203d602011610f9357610f85818361048d565b38612f2e565b612fae613213565b612fb6613213565b6000805160206133cf833981519152805460ff19169055565b908160209103126103f1575190565b60ff6000805160206133cf8339815191525416612ff757565b60405163d93c066560e01b8152600490fd5b9190808302928304036103f157620f424091020490565b908160209103126103f1575160ff811681036103f15790565b60ff60069116019060ff821161264d57565b90601381101561201e5760051b0190565b60405163313ce56760e01b81529091602090829060049082906001600160a01b03165afa908115610f40576000916131e4575b5061317561316f61309e610874565b6001815292600a6020850152606460408501526103e860608501526127106080850152620186a060a0850152620f424060c08501526298968060e08501526305f5e100610100850152633b9aca006101208501526402540be40061014085015264174876e80061016085015264e8d4a510006101808501526509184e72a0006101a0850152655af3107a40006101c085015266038d7ea4c680006101e0850152662386f26fc1000061020085015267016345785d8a0000610220850152670de0b6b3a7640000610240850152613039565b60ff1690565b60068111156131ba576131a861319b6102e794936131956131b494612bce565b9061304b565b516001600160401b031690565b6001600160401b031690565b90612481565b600681106131c757505090565b6131a861319b6102e794936131956131de94612bc0565b90612c47565b613206915060203d60201161320c575b6131fe818361048d565b810190613020565b3861308f565b503d6131f4565b60ff6000805160206133ef8339815191525460401c161561323057565b604051631afcd79f60e31b8152600490fd5b90813b156132c8576000805160206133af83398151915280546001600160a01b0319166001600160a01b0384169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a28051156132ad576132aa916132e9565b50565b5050346132b657565b60405163b398979f60e01b8152600490fd5b604051634c9c8ce360e01b81526001600160a01b0383166004820152602490fd5b6000806102e793602081519101845af43d15613327573d9161330a83610894565b92613318604051948561048d565b83523d6000602085013e61332b565b6060915b90613352575080511561334057805190602001fd5b60405163d6bda27560e01b8152600490fd5b81511580613385575b613363575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b1561335b56fe405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbccd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212200ae85bbb59bcde699351b8945079c40c798bd54e3ccded63d90798899944f93f64736f6c63430008170033","name":"CollateralVault","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":false,"language":"solidity","evm_version":"paris","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"@openzeppelin/contracts/interfaces/draft-IERC1822.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n    /**\n     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n     * address.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy.\n     */\n    function proxiableUUID() external view returns (bytes32);\n}\n"},{"file_path":"@openzeppelin/contracts/utils/introspection/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},{"file_path":"@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (proxy/ERC1967/ERC1967Utils.sol)\n\npragma solidity ^0.8.21;\n\nimport {IBeacon} from \"../beacon/IBeacon.sol\";\nimport {IERC1967} from \"../../interfaces/IERC1967.sol\";\nimport {Address} from \"../../utils/Address.sol\";\nimport {StorageSlot} from \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This library provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.\n */\nlibrary ERC1967Utils {\n    /**\n     * @dev Storage slot with the address of the current implementation.\n     * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1.\n     */\n    // solhint-disable-next-line private-vars-leading-underscore\n    bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    /**\n     * @dev The `implementation` of the proxy is invalid.\n     */\n    error ERC1967InvalidImplementation(address implementation);\n\n    /**\n     * @dev The `admin` of the proxy is invalid.\n     */\n    error ERC1967InvalidAdmin(address admin);\n\n    /**\n     * @dev The `beacon` of the proxy is invalid.\n     */\n    error ERC1967InvalidBeacon(address beacon);\n\n    /**\n     * @dev An upgrade function sees `msg.value > 0` that may be lost.\n     */\n    error ERC1967NonPayable();\n\n    /**\n     * @dev Returns the current implementation address.\n     */\n    function getImplementation() internal view returns (address) {\n        return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the ERC-1967 implementation slot.\n     */\n    function _setImplementation(address newImplementation) private {\n        if (newImplementation.code.length == 0) {\n            revert ERC1967InvalidImplementation(newImplementation);\n        }\n        StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\n    }\n\n    /**\n     * @dev Performs implementation upgrade with additional setup call if data is nonempty.\n     * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\n     * to avoid stuck value in the contract.\n     *\n     * Emits an {IERC1967-Upgraded} event.\n     */\n    function upgradeToAndCall(address newImplementation, bytes memory data) internal {\n        _setImplementation(newImplementation);\n        emit IERC1967.Upgraded(newImplementation);\n\n        if (data.length > 0) {\n            Address.functionDelegateCall(newImplementation, data);\n        } else {\n            _checkNonPayable();\n        }\n    }\n\n    /**\n     * @dev Storage slot with the admin of the contract.\n     * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1.\n     */\n    // solhint-disable-next-line private-vars-leading-underscore\n    bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n    /**\n     * @dev Returns the current admin.\n     *\n     * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\n     * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n     * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n     */\n    function getAdmin() internal view returns (address) {\n        return StorageSlot.getAddressSlot(ADMIN_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the ERC-1967 admin slot.\n     */\n    function _setAdmin(address newAdmin) private {\n        if (newAdmin == address(0)) {\n            revert ERC1967InvalidAdmin(address(0));\n        }\n        StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\n    }\n\n    /**\n     * @dev Changes the admin of the proxy.\n     *\n     * Emits an {IERC1967-AdminChanged} event.\n     */\n    function changeAdmin(address newAdmin) internal {\n        emit IERC1967.AdminChanged(getAdmin(), newAdmin);\n        _setAdmin(newAdmin);\n    }\n\n    /**\n     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n     * This is the keccak-256 hash of \"eip1967.proxy.beacon\" subtracted by 1.\n     */\n    // solhint-disable-next-line private-vars-leading-underscore\n    bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n    /**\n     * @dev Returns the current beacon.\n     */\n    function getBeacon() internal view returns (address) {\n        return StorageSlot.getAddressSlot(BEACON_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new beacon in the ERC-1967 beacon slot.\n     */\n    function _setBeacon(address newBeacon) private {\n        if (newBeacon.code.length == 0) {\n            revert ERC1967InvalidBeacon(newBeacon);\n        }\n\n        StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\n\n        address beaconImplementation = IBeacon(newBeacon).implementation();\n        if (beaconImplementation.code.length == 0) {\n            revert ERC1967InvalidImplementation(beaconImplementation);\n        }\n    }\n\n    /**\n     * @dev Change the beacon and trigger a setup call if data is nonempty.\n     * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\n     * to avoid stuck value in the contract.\n     *\n     * Emits an {IERC1967-BeaconUpgraded} event.\n     *\n     * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\n     * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\n     * efficiency.\n     */\n    function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\n        _setBeacon(newBeacon);\n        emit IERC1967.BeaconUpgraded(newBeacon);\n\n        if (data.length > 0) {\n            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n        } else {\n            _checkNonPayable();\n        }\n    }\n\n    /**\n     * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\n     * if an upgrade doesn't perform an initialization call.\n     */\n    function _checkNonPayable() private {\n        if (msg.value > 0) {\n            revert ERC1967NonPayable();\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Context.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\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    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"},{"file_path":"contracts/utils/AccessChecker.sol","source_code":"// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.23;\r\n\r\nimport '../interfaces/access/IAccessController.sol';\r\nimport '../errors/ISystemErrors.sol';\r\n\r\n/**\r\n * @title Access Checker Library\r\n * @notice Utility functions for access control checks\r\n * @dev Provides reusable access control functionality\r\n */\r\nlibrary AccessChecker {\r\n    /**\r\n     * @notice Verifies caller has required role\r\n     * @param accessController Access controller contract\r\n     * @param role Required role\r\n     * @param account Account to check\r\n     */\r\n    function checkRole(\r\n        IAccessController accessController,\r\n        bytes32 role,\r\n        address account\r\n    ) internal view {\r\n        if (!accessController.hasRole(role, account)) {\r\n            revert ISystemErrors.Unauthorized(string(abi.encodePacked('Missing role: ', role)));\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Verifies caller has one of required roles\r\n     * @param accessController Access controller contract\r\n     * @param roles Array of acceptable roles\r\n     * @param account Account to check\r\n     */\r\n    function checkRoles(\r\n        IAccessController accessController,\r\n        bytes32[] memory roles,\r\n        address account\r\n    ) internal view {\r\n        for (uint i = 0; i < roles.length; i++) {\r\n            if (accessController.hasRole(roles[i], account)) {\r\n                return;\r\n            }\r\n        }\r\n        revert ISystemErrors.Unauthorized('Missing required roles');\r\n    }\r\n\r\n    /**\r\n     * @notice Validates contract address\r\n     * @param addr Address to validate\r\n     */\r\n    function validateAddress(address addr) internal pure {\r\n        if (addr == address(0)) {\r\n            revert ISystemErrors.InvalidAddress(addr);\r\n        }\r\n    }\r\n}\r\n"},{"file_path":"@openzeppelin/contracts/utils/Address.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\nimport {Errors} from \"./Errors.sol\";\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert Errors.InsufficientBalance(address(this).balance, amount);\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert Errors.FailedCall();\n        }\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {Errors.FailedCall} error.\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert Errors.InsufficientBalance(address(this).balance, value);\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\n     * of an unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {Errors.FailedCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.\n     */\n    function _revert(bytes memory returndata) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            assembly (\"memory-safe\") {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert Errors.FailedCall();\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\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    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC721/IERC721.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC-721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n     *   a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC-721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or\n     *   {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n     *   a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721\n     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n     * understand this adds an external call which potentially creates a reentrancy vulnerability.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the address zero.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n"},{"file_path":"contracts/libraries/SystemRoles.sol","source_code":"// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.23;\r\nimport '../utils/Constants.sol';\r\n\r\n/**\r\n * @title System Roles\r\n * @notice Defines roles and their configurations\r\n * @dev Uses constants from main Constants library\r\n * @author ZeUSD Protocol Team\r\n * @custom:security-contact paras@zoth.io\r\n */\r\nlibrary SystemRoles {\r\n    // Core Administrative Roles\r\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\r\n    bytes32 public constant EMERGENCY_ROLE = keccak256('EMERGENCY_ROLE');\r\n    bytes32 public constant UPGRADER_ROLE = keccak256('UPGRADER_ROLE');\r\n    bytes32 public constant WITHDRAWAL_MANAGER_ROLE = keccak256('WITHDRAWAL_MANAGER_ROLE');\r\n\r\n    // Vault Management Roles\r\n    bytes32 public constant VAULT_ADMIN_ROLE = keccak256('VAULT_ADMIN_ROLE');\r\n    bytes32 public constant ASSET_MANAGER_ROLE = keccak256('ASSET_MANAGER_ROLE');\r\n\r\n    // Risk & Control Roles\r\n    bytes32 public constant RISK_CONTROLLER_ROLE = keccak256('RISK_CONTROLLER_ROLE');\r\n    bytes32 public constant LIQUIDATOR_ROLE = keccak256('LIQUIDATOR_ROLE');\r\n    bytes32 public constant PRICE_ADMIN_ROLE = keccak256('PRICE_ADMIN_ROLE');\r\n\r\n    // Rewards & Incentives\r\n    bytes32 public constant REWARD_MANAGER_ROLE = keccak256('REWARD_MANAGER_ROLE');\r\n\r\n    /**\r\n     * @notice Role configuration data structure\r\n     * @param adminRole Role that can grant/revoke this role\r\n     * @param timelock Required delay for critical operations\r\n     * @param requiresConsensus Whether consensus is required\r\n     * @param revocable Whether role can be revoked\r\n     * @param pausable Whether role can be paused\r\n     */\r\n    struct RoleConfig {\r\n        bytes32 adminRole;\r\n        uint256 timelock;\r\n        bool requiresConsensus;\r\n        bool revocable;\r\n        bool pausable;\r\n    }\r\n\r\n    /**\r\n     * @notice Permission configuration data structure\r\n     * @param role Role identifier\r\n     * @param functionSig Function signature\r\n     * @param enabled Whether permission is active\r\n     * @param restrictions Additional restrictions (bitmap)\r\n     */\r\n    struct Permission {\r\n        bytes32 role;\r\n        bytes4 functionSig;\r\n        bool enabled;\r\n        uint256 restrictions;\r\n    }\r\n\r\n    /**\r\n     * @notice Returns DEFAULT_ADMIN_ROLE configuration\r\n     * @dev Highest authority, requires consensus and delay\r\n     */\r\n    function getDefaultAdminConfig() internal pure returns (RoleConfig memory) {\r\n        return\r\n            RoleConfig({\r\n                adminRole: DEFAULT_ADMIN_ROLE,\r\n                timelock: Constants.TWO_DAYS,\r\n                requiresConsensus: true,\r\n                revocable: false,\r\n                pausable: false\r\n            });\r\n    }\r\n\r\n    /**\r\n     * @notice Returns EMERGENCY_ROLE configuration\r\n     * @dev Quick response role, no delay but revocable\r\n     */\r\n    function getEmergencyConfig() internal pure returns (RoleConfig memory) {\r\n        return\r\n            RoleConfig({\r\n                adminRole: DEFAULT_ADMIN_ROLE,\r\n                timelock: 0,\r\n                requiresConsensus: false,\r\n                revocable: true,\r\n                pausable: true\r\n            });\r\n    }\r\n\r\n    /**\r\n     * @notice Returns UPGRADER_ROLE configuration\r\n     * @dev Contract upgrade role, requires consensus\r\n     */\r\n    function getWithdrawalManagerConfig() internal pure returns (RoleConfig memory) {\r\n        return\r\n            RoleConfig({\r\n                adminRole: DEFAULT_ADMIN_ROLE,\r\n                timelock: Constants.ONE_DAY,\r\n                requiresConsensus: true,\r\n                revocable: true,\r\n                pausable: true\r\n            });\r\n    }\r\n\r\n    /**\r\n     * @notice Returns UPGRADER_ROLE configuration\r\n     * @dev Contract upgrade role, requires consensus\r\n     */\r\n    function getUpgraderConfig() internal pure returns (RoleConfig memory) {\r\n        return\r\n            RoleConfig({\r\n                adminRole: DEFAULT_ADMIN_ROLE,\r\n                timelock: Constants.ONE_DAY,\r\n                requiresConsensus: true,\r\n                revocable: true,\r\n                pausable: true\r\n            });\r\n    }\r\n\r\n    /**\r\n     * @notice Returns VAULT_ADMIN_ROLE configuration\r\n     * @dev Vault management role with delay\r\n     */\r\n    function getVaultAdminConfig() internal pure returns (RoleConfig memory) {\r\n        return\r\n            RoleConfig({\r\n                adminRole: DEFAULT_ADMIN_ROLE,\r\n                timelock: Constants.ONE_DAY,\r\n                requiresConsensus: true,\r\n                revocable: true,\r\n                pausable: true\r\n            });\r\n    }\r\n\r\n    /**\r\n     * @notice Returns ASSET_MANAGER_ROLE configuration\r\n     * @dev Asset management under vault admin\r\n     */\r\n    function getAssetManagerConfig() internal pure returns (RoleConfig memory) {\r\n        return\r\n            RoleConfig({\r\n                adminRole: VAULT_ADMIN_ROLE,\r\n                timelock: Constants.TWELVE_HOURS,\r\n                requiresConsensus: true,\r\n                revocable: true,\r\n                pausable: true\r\n            });\r\n    }\r\n\r\n    /**\r\n     * @notice Returns RISK_CONTROLLER_ROLE configuration\r\n     * @dev Risk parameter management role\r\n     */\r\n    function getRiskControllerConfig() internal pure returns (RoleConfig memory) {\r\n        return\r\n            RoleConfig({\r\n                adminRole: DEFAULT_ADMIN_ROLE,\r\n                timelock: Constants.TWELVE_HOURS,\r\n                requiresConsensus: true,\r\n                revocable: true,\r\n                pausable: true\r\n            });\r\n    }\r\n\r\n    /**\r\n     * @notice Returns LIQUIDATOR_ROLE configuration\r\n     * @dev Liquidation execution role, no delay\r\n     */\r\n    function getLiquidatorConfig() internal pure returns (RoleConfig memory) {\r\n        return\r\n            RoleConfig({\r\n                adminRole: RISK_CONTROLLER_ROLE,\r\n                timelock: 0,\r\n                requiresConsensus: false,\r\n                revocable: true,\r\n                pausable: true\r\n            });\r\n    }\r\n\r\n    /**\r\n     * @notice Returns PRICE_ADMIN_ROLE configuration\r\n     * @dev Oracle management role\r\n     */\r\n    function getPriceAdminConfig() internal pure returns (RoleConfig memory) {\r\n        return\r\n            RoleConfig({\r\n                adminRole: DEFAULT_ADMIN_ROLE,\r\n                timelock: Constants.TWELVE_HOURS,\r\n                requiresConsensus: true,\r\n                revocable: true,\r\n                pausable: true\r\n            });\r\n    }\r\n\r\n    /**\r\n     * @notice Returns REWARD_MANAGER_ROLE configuration\r\n     * @dev Rewards management role\r\n     */\r\n    function getRewardManagerConfig() internal pure returns (RoleConfig memory) {\r\n        return\r\n            RoleConfig({\r\n                adminRole: DEFAULT_ADMIN_ROLE,\r\n                timelock: Constants.ONE_DAY,\r\n                requiresConsensus: true,\r\n                revocable: true,\r\n                pausable: true\r\n            });\r\n    }\r\n}\r\n"},{"file_path":"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC721} from \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Enumerable is IERC721 {\n    /**\n     * @dev Returns the total amount of tokens stored by the contract.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.\n     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.\n     */\n    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);\n\n    /**\n     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.\n     * Use along with {totalSupply} to enumerate all tokens.\n     */\n    function tokenByIndex(uint256 index) external view returns (uint256);\n}\n"},{"file_path":"contracts/interfaces/ICollateralVault.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\r\npragma solidity 0.8.23;\r\n\r\nimport '../events/ICollateralVaultEvents.sol';\r\nimport '../errors/ICollateralVaultErrors.sol';\r\nimport '../libraries/DataTypes.sol';\r\n\r\n/**\r\n * @title Collateral Vault Interface\r\n * @author ZeUSD Protocol Team\r\n * @notice Main interface for the CollateralVault contract defining all external functions\r\n * @dev Implements UUPS upgradeable pattern functionality\r\n */\r\ninterface ICollateralVault is ICollateralVaultEvents, ICollateralVaultErrors {\r\n    /**\r\n     * @notice Sets the router contract address\r\n     * @param _router Address of the router contract\r\n     * @dev Can only be set once by admin\r\n     */\r\n    function setRouter(address _router) external;\r\n\r\n    /**\r\n     * @notice Registers or updates a subvault configuration\r\n     * @param integrationType Type of integration\r\n     * @param collateralAddress Address of the collateral asset\r\n     * @param subVaultAddress Address of the subvault\r\n     * @param price Price of the collateral\r\n     * @param ltv Loan-to-Value ratio\r\n     * @param isActive Active status of the subvault\r\n     * @param tokenType Token classification\r\n     * @dev Only callable by ADMIN_ROLE\r\n     */\r\n    function registerSubVault(\r\n        string calldata integrationType,\r\n        address collateralAddress,\r\n        address subVaultAddress,\r\n        uint256 price,\r\n        uint256 ltv,\r\n        bool isActive,\r\n        DataTypes.TokenType tokenType\r\n    ) external;\r\n\r\n    /**\r\n     * @notice Updates specific parameters of a subvault\r\n     * @param collateralAddress Address of the collateral asset\r\n     * @param params Update parameters struct\r\n     * @dev Only callable by ADMIN_ROLE\r\n     */\r\n    function updateSubVaultConfig(\r\n        address collateralAddress,\r\n        DataTypes.SubVaultUpdateParams calldata params\r\n    ) external;\r\n\r\n    /**\r\n     * @notice Calculates the amount of ZeUSD that can be minted for a given collateral amount\r\n     * @param collateralAddress Address of the collateral asset\r\n     * @param asset Address of the specific asset being used\r\n     * @param tokenType Type classification of the token\r\n     * @param amount Amount of collateral being considered\r\n     * @return mintAmount Amount of ZeUSD that can be minted\r\n     */\r\n    function calculateMintAmount(\r\n        address collateralAddress,\r\n        address asset,\r\n        DataTypes.TokenType tokenType,\r\n        uint256 amount\r\n    ) external view returns (uint256 mintAmount);\r\n\r\n    /**\r\n     * @notice Retrieves all registered subvaults and their details\r\n     * @return collaterals Array of collateral addresses\r\n     * @return details Array of corresponding CollateralDetails structs\r\n     */\r\n    function getAllSubVaults()\r\n        external\r\n        view\r\n        returns (address[] memory collaterals, DataTypes.CollateralDetails[] memory details);\r\n\r\n    /**\r\n     * @notice Retrieves all active subvaults and their details\r\n     * @return collaterals Array of active collateral addresses\r\n     * @return details Array of corresponding CollateralDetails structs\r\n     */\r\n    function getActiveSubVaults()\r\n        external\r\n        view\r\n        returns (address[] memory collaterals, DataTypes.CollateralDetails[] memory details);\r\n\r\n    /**\r\n     * @notice Gets the subvault address for a given collateral\r\n     * @param collateralAddress Address of the collateral asset\r\n     * @return subVaultAddress Address of the corresponding subvault\r\n     */\r\n    function getSubVaultAddress(\r\n        address collateralAddress\r\n    ) external view returns (address subVaultAddress);\r\n\r\n    /**\r\n     * @notice Gets full configuration details for a collateral's subvault\r\n     * @param collateralAddress Address of the collateral asset\r\n     * @return details Full configuration details struct\r\n     */\r\n    function getSubVaultDetails(\r\n        address collateralAddress\r\n    ) external view returns (DataTypes.CollateralDetails memory details);\r\n\r\n    /**\r\n     * @notice Gets count of registered and active subvaults\r\n     * @return total Total number of registered subvaults\r\n     * @return active Number of active subvaults\r\n     */\r\n    function getSubVaultCounts() external view returns (uint256 total, uint256 active);\r\n\r\n    /**\r\n     * @notice Removes a subvault registration\r\n     * @param collateralAddress Address of the collateral asset\r\n     * @dev Only callable by ADMIN_ROLE\r\n     */\r\n    function removeSubVault(address collateralAddress) external;\r\n\r\n    /**\r\n     * @notice Pauses all vault operations\r\n     * @dev Only callable by ADMIN_ROLE\r\n     */\r\n    function pause() external;\r\n\r\n    /**\r\n     * @notice Unpauses vault operations\r\n     * @dev Only callable by ADMIN_ROLE\r\n     */\r\n    function unpause() external;\r\n\r\n    /**\r\n     * @notice Validates and prepares deposit parameters\r\n     * @param user Address of the depositor\r\n     * @param collateralAddress Address of the collateral asset\r\n     * @param asset Address of the specific asset being deposited\r\n     * @param amount Amount being deposited\r\n     * @param tokenId ID of the NFT\r\n     * @return metadata Deposit metadata for NFT\r\n     */\r\n    function validateAndPrepareDeposit(\r\n        address user,\r\n        address collateralAddress,\r\n        address asset,\r\n        uint256 amount,\r\n        uint256 tokenId\r\n    ) external view returns (DataTypes.DepositMetadata memory metadata);\r\n\r\n    /**\r\n     * @notice Gets user active positions for a specific subvault\r\n     * @param user Address to query positions for\r\n     * @param subVault Subvault to filter by\r\n     * @return metadata Array of active deposit metadata\r\n     */\r\n    function getUserActivePositionsBySubVault(\r\n        address user,\r\n        address subVault\r\n    ) external view returns (DataTypes.DepositMetadata[] memory metadata);\r\n}\r\n"},{"file_path":"contracts/interfaces/access/IAccessController.sol","source_code":"// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.23;\r\n\r\nimport '../../libraries/SystemRoles.sol';\r\n\r\n/**\r\n * @title Access Controller Interface\r\n * @author ZeUSD Protocol Team\r\n * @notice Interface for managing role-based access control across the protocol\r\n * @dev Combines standard role management with custom role configuration\r\n * @custom:security-contact paras@zoth.io\r\n */\r\ninterface IAccessController {\r\n    /**\r\n     * @notice Checks if an account has a specific role\r\n     * @param role Role identifier to check\r\n     * @param account Account to verify\r\n     * @return bool True if account has the role\r\n     * @dev Core function for role verification\r\n     */\r\n    function hasRole(bytes32 role, address account) external view returns (bool);\r\n\r\n    /**\r\n     * @notice Grants a role to an account\r\n     * @param role Role to grant\r\n     * @param account Account to receive the role\r\n     * @dev Only callable by role admin\r\n     */\r\n    function grantRole(bytes32 role, address account) external;\r\n\r\n    /**\r\n     * @notice Revokes a role from an account\r\n     * @param role Role to revoke\r\n     * @param account Account to revoke from\r\n     * @dev Only callable by role admin\r\n     */\r\n    function revokeRole(bytes32 role, address account) external;\r\n\r\n    /**\r\n     * @notice Gets configuration for a specific role\r\n     * @param role Role identifier\r\n     * @return RoleConfig Configuration struct for the role\r\n     * @dev Returns role settings and constraints\r\n     */\r\n    function getRoleConfig(bytes32 role) external view returns (SystemRoles.RoleConfig memory);\r\n\r\n    /**\r\n     * @notice Initializes a new role with configuration\r\n     * @param role Role identifier to initialize\r\n     * @param config Role configuration settings\r\n     * @param adminRole Role that will administer this role\r\n     * @dev Sets up new role with specified parameters\r\n     */\r\n    function initializeRole(\r\n        bytes32 role,\r\n        SystemRoles.RoleConfig memory config,\r\n        bytes32 adminRole\r\n    ) external;\r\n\r\n    /**\r\n     * @notice Gets the admin role for a role\r\n     * @param role Role to query\r\n     * @return bytes32 Admin role identifier\r\n     * @dev Returns role that can manage the queried role\r\n     */\r\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\r\n\r\n    /**\r\n     * @notice Sets the admin role for a role\r\n     * @param role Role to modify\r\n     * @param adminRole New admin role\r\n     * @dev Changes which role can manage the specified role\r\n     */\r\n    function setRoleAdmin(bytes32 role, bytes32 adminRole) external;\r\n\r\n    /**\r\n     * @notice Gets all members with a specific role\r\n     * @param role Role to query\r\n     * @return address[] Array of addresses with the role\r\n     * @dev Returns complete list of role members\r\n     */\r\n    function getRoleMembers(bytes32 role) external view returns (address[] memory);\r\n\r\n    /**\r\n     * @notice Checks if a role has been initialized\r\n     * @param role Role to check\r\n     * @return bool True if role is initialized\r\n     * @dev Verifies role existence and setup\r\n     */\r\n    function isRoleInitialized(bytes32 role) external view returns (bool);\r\n}\r\n"},{"file_path":"contracts/interfaces/IZeUSD_CDP.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\r\npragma solidity 0.8.23;\r\n\r\nimport '../libraries/DataTypes.sol';\r\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\r\nimport '@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol';\r\n\r\n/**\r\n * @title Deposit NFT Interface\r\n * @author ZeUSD Protocol Team\r\n * @notice Interface for managing deposit NFTs in the ZeUSD protocol\r\n * @dev Extends ERC721 functionality with deposit-specific features\r\n */\r\ninterface IZeUSD_CDP is IERC721Enumerable {\r\n    /**\r\n     * @notice Gets all token IDs owned by a specific address\r\n     * @dev Used for retrieving user's deposit positions\r\n     * @param owner Address to query\r\n     * @return Array of token IDs owned by the address\r\n     * @custom:security No access control required, public view\r\n     */\r\n    function getTokensByOwner(address owner) external view returns (uint256[] memory);\r\n\r\n    /**\r\n     * @notice Gets deposit details for a specific token ID\r\n     * @dev Retrieves the original deposit metadata associated with the NFT\r\n     * @param tokenId ID of the token to query\r\n     * @return metadata Deposit metadata for NFT\r\n     * @custom:security Token must exist\r\n     */\r\n    function getDepositDetails(\r\n        uint256 tokenId\r\n    ) external view returns (DataTypes.DepositMetadata memory metadata);\r\n\r\n    /**\r\n     * @notice Mints a new NFT with deposit details\r\n     * @dev Creates a new deposit NFT and stores associated metadata\r\n     * @param to Address to mint the NFT to\r\n     * @param metadata Deposit metadata to associate with the NFT\r\n     * @return tokenId ID of the newly minted NFT\r\n     * @custom:security Only callable by router\r\n     * @custom:emits Transfer\r\n     */\r\n    function mint(\r\n        address to,\r\n        DataTypes.DepositMetadata calldata metadata\r\n    ) external returns (uint256);\r\n\r\n    /**\r\n     * @notice Burns an NFT\r\n     * @dev Permanently removes an NFT and its associated metadata\r\n     * @param tokenId ID of the token to burn\r\n     * @custom:security Only callable by authorized contracts\r\n     * @custom:emits Transfer to zero address\r\n     */\r\n    function burn(uint256 tokenId) external;\r\n\r\n    /**\r\n     * @notice Gets the next token ID without incrementing\r\n     * @return The next token ID that will be used\r\n     */\r\n    function getNextTokenId() external view returns (uint256);\r\n}\r\n"},{"file_path":"contracts/utils/Constants.sol","source_code":"// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.23;\r\n\r\n/**\r\n * @title Protocol Constants\r\n * @author ZeUSD Protocol Team\r\n * @notice Central source for all protocol constants\r\n * @dev Single source of truth for contract identifiers and constants\r\n * @custom:security Constants should never be modified after deployment\r\n */\r\nlibrary Constants {\r\n    /**\r\n     * @notice Protocol Contract Identifiers\r\n     * @dev Unique identifiers for protocol contracts in registry\r\n     */\r\n    bytes32 public constant CONTRACT_ACCESS_CONTROLLER = keccak256('CONTRACT_ACCESS_CONTROLLER');\r\n    bytes32 public constant CONTRACT_REGISTRY = keccak256('CONTRACT_REGISTRY');\r\n    bytes32 public constant CONTRACT_ZEUSD = keccak256('CONTRACT_ZEUSD');\r\n    bytes32 public constant CONTRACT_ROUTER = keccak256('CONTRACT_ROUTER');\r\n    bytes32 public constant CONTRACT_TREASURY = keccak256('CONTRACT_TREASURY');\r\n    bytes32 public constant CONTRACT_ORACLE = keccak256('CONTRACT_ORACLE');\r\n    bytes32 public constant CONTRACT_DEPOSIT_NFT = keccak256('CONTRACT_DEPOSIT_NFT');\r\n    bytes32 public constant CONTRACT_WITHDRAWAL_SYSTEM = keccak256('CONTRACT_WITHDRAWAL_SYSTEM');\r\n\r\n    /**\r\n     * @notice Time Constants\r\n     * @dev Standard time periods used throughout the protocol\r\n     */\r\n    uint256 public constant ONE_HOUR = 1 hours;\r\n    uint256 public constant ONE_DAY = 1 days;\r\n    uint256 public constant ONE_WEEK = 7 days;\r\n    uint256 public constant TWO_DAYS = 2 days;\r\n    uint256 public constant TWELVE_HOURS = 12 hours;\r\n\r\n    /**\r\n     * @notice Protocol Parameters\r\n     * @dev Governance and operational limits\r\n     */\r\n    /// @notice Maximum number of roles a single account can hold\r\n    uint256 public constant MAX_ROLES_PER_ACCOUNT = 10;\r\n\r\n    /// @notice Maximum number of members that can be assigned to a role\r\n    uint256 public constant MAX_MEMBERS_PER_ROLE = 50;\r\n\r\n    /// @notice Percentage threshold required for consensus decisions (66%)\r\n    uint256 public constant CONSENSUS_THRESHOLD = 66;\r\n\r\n    /// @notice Delay period for emergency actions\r\n    uint256 public constant EMERGENCY_DELAY = 1 hours;\r\n}\r\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/ERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC20Metadata} from \"./extensions/IERC20Metadata.sol\";\nimport {Context} from \"../../utils/Context.sol\";\nimport {IERC20Errors} from \"../../interfaces/draft-IERC6093.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC-20\n * applications.\n */\nabstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {\n    mapping(address account => uint256) private _balances;\n\n    mapping(address account => mapping(address spender => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the default value returned by this function, unless\n     * it's overridden.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `value`.\n     */\n    function transfer(address to, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, value);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, value);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Skips emitting an {Approval} event indicating an allowance update. This is not\n     * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `value`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `value`.\n     */\n    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, value);\n        _transfer(from, to, value);\n        return true;\n    }\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _transfer(address from, address to, uint256 value) internal {\n        if (from == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        if (to == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(from, to, value);\n    }\n\n    /**\n     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\n     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\n     * this function.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _update(address from, address to, uint256 value) internal virtual {\n        if (from == address(0)) {\n            // Overflow check required: The rest of the code assumes that totalSupply never overflows\n            _totalSupply += value;\n        } else {\n            uint256 fromBalance = _balances[from];\n            if (fromBalance < value) {\n                revert ERC20InsufficientBalance(from, fromBalance, value);\n            }\n            unchecked {\n                // Overflow not possible: value <= fromBalance <= totalSupply.\n                _balances[from] = fromBalance - value;\n            }\n        }\n\n        if (to == address(0)) {\n            unchecked {\n                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\n                _totalSupply -= value;\n            }\n        } else {\n            unchecked {\n                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\n                _balances[to] += value;\n            }\n        }\n\n        emit Transfer(from, to, value);\n    }\n\n    /**\n     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\n     * Relies on the `_update` mechanism\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _mint(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(address(0), account, value);\n    }\n\n    /**\n     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\n     * Relies on the `_update` mechanism.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead\n     */\n    function _burn(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        _update(account, address(0), value);\n    }\n\n    /**\n     * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     *\n     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n     */\n    function _approve(address owner, address spender, uint256 value) internal {\n        _approve(owner, spender, value, true);\n    }\n\n    /**\n     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\n     *\n     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\n     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any\n     * `Approval` event during `transferFrom` operations.\n     *\n     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to\n     * true using the following override:\n     *\n     * ```solidity\n     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\n     *     super._approve(owner, spender, value, true);\n     * }\n     * ```\n     *\n     * Requirements are the same as {_approve}.\n     */\n    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\n        if (owner == address(0)) {\n            revert ERC20InvalidApprover(address(0));\n        }\n        if (spender == address(0)) {\n            revert ERC20InvalidSpender(address(0));\n        }\n        _allowances[owner][spender] = value;\n        if (emitEvent) {\n            emit Approval(owner, spender, value);\n        }\n    }\n\n    /**\n     * @dev Updates `owner` s allowance for `spender` based on spent `value`.\n     *\n     * Does not update the allowance value in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Does not emit an {Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance != type(uint256).max) {\n            if (currentAllowance < value) {\n                revert ERC20InsufficientAllowance(spender, currentAllowance, value);\n            }\n            unchecked {\n                _approve(owner, spender, currentAllowance - value, false);\n            }\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/proxy/beacon/IBeacon.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n    /**\n     * @dev Must return an address that can be used as a delegate call target.\n     *\n     * {UpgradeableBeacon} will check that this address is a contract.\n     */\n    function implementation() external view returns (address);\n}\n"},{"file_path":"contracts/interfaces/ISubVault.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\r\npragma solidity 0.8.23;\r\n\r\nimport '../events/ISubVaultEvents.sol';\r\nimport '../errors/ISubVaultErrors.sol';\r\n\r\n/**\r\n * @title Asset Specific SubVault Interface\r\n * @author ZeUSD Protocol Team\r\n * @notice Interface for specialized vaults handling primary and secondary assets\r\n * @dev Implements deposit/withdrawal functionality with primary asset focus\r\n * @custom:security-contact paras@zoth.io\r\n */\r\ninterface ISubVault is ISubVaultEvents, ISubVaultErrors {\r\n    /// @notice SECURITY CONSIDERATIONS:\r\n    /// - Primary asset operations must be validated separately\r\n    /// - Secondary assets require additional validation\r\n    /// - Balance checks before all operations\r\n    /// - Emergency mode restrictions\r\n    /// - Proper approval management for FundVaultV2\r\n    /// - Asset-specific transfer validations\r\n    ///\r\n    /// STATE MANAGEMENT:\r\n    /// - Normal: Full functionality for all assets\r\n    /// - Paused: No operations allowed\r\n    /// - Emergency: Only emergency withdrawals\r\n    /// - Primary Asset: Always supported\r\n    /// - Secondary Assets: Can be added/removed\r\n    ///\r\n    /// INTEGRATION REQUIREMENTS:\r\n    /// - Must validate primary asset operations first\r\n    /// - Must implement separate flows for primary/secondary assets\r\n    /// - Must maintain accurate balances for all assets\r\n    /// - Must emit appropriate events for tracking\r\n    /// - Must handle FundVaultV2 interactions safely\r\n    /// - Must implement proper access control\r\n    ///\r\n    /// ASSET HANDLING:\r\n    /// Primary Asset:\r\n    /// - Cannot be removed\r\n    /// - Direct integration with FundVaultV2\r\n    /// - Specialized event emission\r\n    ///\r\n    /// Secondary Assets:\r\n    /// - Can be added/removed by admin\r\n    /// - May require conversion logic\r\n    /// - Separate event emission\r\n\r\n    /**\r\n     * @notice Handles deposit of any supported asset\r\n     * @param user Address of the depositing user\r\n     * @param asset Address of the asset being deposited\r\n     * @param amount Amount to deposit\r\n     * @return success Whether the deposit was successful\r\n     * @dev Different handling for primary vs secondary assets\r\n     */\r\n    function handleDeposit(address user, address asset, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @notice Handles withdrawal of any supported asset\r\n     * @param user Address of the withdrawing user\r\n     * @param asset Address of the asset to withdraw\r\n     * @param amount Amount to withdraw\r\n     * @return success Whether the withdrawal was successful\r\n     * @dev Different handling for primary vs secondary assets\r\n     */\r\n    function handleWithdraw(address user, address asset, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @notice Gets the current oracle price for the asset if available\r\n     * @param asset Address of the asset to get price for\r\n     * @return price Current oracle price (0 if not available)\r\n     * @return success Whether oracle price was successfully fetched\r\n     */\r\n    function getOraclePrice(address asset) external view returns (uint256 price, bool success);\r\n\r\n    /**\r\n     * @notice Executes emergency withdrawal for any supported asset\r\n     * @param asset Address of the asset to withdraw\r\n     * @param to Recipient address\r\n     * @param amount Amount to withdraw\r\n     * @param reason Reason for emergency withdrawal\r\n     * @return success Whether the withdrawal was successful\r\n     * @dev Available in emergency mode only, special handling for primary asset\r\n     */\r\n    function withdrawEmergency(\r\n        address asset,\r\n        address to,\r\n        uint256 amount,\r\n        string calldata reason\r\n    ) external returns (bool);\r\n\r\n    /**\r\n     * @notice Adds support for a secondary asset\r\n     * @param asset Address of the asset to add\r\n     * @param reason Reason for adding the asset\r\n     * @dev Cannot add primary asset, reverts if asset already supported\r\n     */\r\n    function addAsset(address asset, string calldata reason) external;\r\n\r\n    /**\r\n     * @notice Removes support for a secondary asset\r\n     * @param asset Address of the asset to remove\r\n     * @param reason Reason for removing the asset\r\n     * @dev Cannot remove primary asset, reverts if asset not supported\r\n     */\r\n    function removeAsset(address asset, string calldata reason) external;\r\n\r\n    /**\r\n     * @notice Gets complete list of supported assets\r\n     * @return Array of supported asset addresses\r\n     * @dev Primary asset is always first in the array\r\n     */\r\n    function getSupportedAssets() external view returns (address[] memory);\r\n\r\n    /**\r\n     * @notice Gets true for supported asset\r\n     * @param asset Address of the asset to check\r\n     * @return Whether the asset is supported\r\n     */\r\n    function isAssetSupported(address asset) external view returns (bool);\r\n\r\n    /**\r\n     * @notice Gets current emergency status\r\n     * @return isEmergencyMode Whether emergency mode is active\r\n     * @return isPaused Whether vault is paused\r\n     * @return timeUntilNextAction Time until next emergency action allowed\r\n     * @dev Used to check vault status before operations\r\n     */\r\n    function getEmergencyStatus()\r\n        external\r\n        view\r\n        returns (bool isEmergencyMode, bool isPaused, uint256 timeUntilNextAction);\r\n\r\n    /**\r\n     * @notice Checks if an asset is the primary asset\r\n     * @param asset Asset address to check\r\n     * @return bool True if asset is primary asset\r\n     * @dev Used to determine asset handling flow\r\n     */\r\n    function isPrimaryAsset(address asset) external view returns (bool);\r\n\r\n    /**\r\n     * @notice Gets the primary asset address\r\n     * @return address Address of primary asset\r\n     * @dev Primary asset cannot be changed after deployment\r\n     */\r\n    function getPrimaryAsset() external view returns (address);\r\n\r\n    /**\r\n     * @notice Enables emergency mode\r\n     * @dev Pauses operations and starts emergency delay timer\r\n     */\r\n    function enableEmergencyMode() external;\r\n\r\n    /**\r\n     * @notice Disables emergency mode\r\n     * @dev Can only be called after emergency delay period\r\n     */\r\n    function disableEmergencyMode() external;\r\n\r\n    /**\r\n     * @notice Pauses all vault operations\r\n     * @dev Separate from emergency mode\r\n     */\r\n    function pause() external;\r\n\r\n    /**\r\n     * @notice Unpauses vault operations\r\n     * @dev Cannot unpause if in emergency mode\r\n     */\r\n    function unpause() external;\r\n}\r\n"},{"file_path":"@openzeppelin/contracts/utils/Errors.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of common custom errors used in multiple contracts\n *\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\n * It is recommended to avoid relying on the error API for critical functionality.\n *\n * _Available since v5.1._\n */\nlibrary Errors {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error InsufficientBalance(uint256 balance, uint256 needed);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedCall();\n\n    /**\n     * @dev The deployment failed.\n     */\n    error FailedDeployment();\n\n    /**\n     * @dev A necessary precompile is missing.\n     */\n    error MissingPrecompile(address);\n}\n"},{"file_path":"@openzeppelin/contracts/interfaces/IERC1967.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n */\ninterface IERC1967 {\n    /**\n     * @dev Emitted when the implementation is upgraded.\n     */\n    event Upgraded(address indexed implementation);\n\n    /**\n     * @dev Emitted when the admin account has changed.\n     */\n    event AdminChanged(address previousAdmin, address newAdmin);\n\n    /**\n     * @dev Emitted when the beacon is changed.\n     */\n    event BeaconUpgraded(address indexed beacon);\n}\n"},{"file_path":"contracts/errors/ISubVaultErrors.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\r\npragma solidity 0.8.23;\r\n\r\n/**\r\n * @title SubVault Errors Interface\r\n * @author ZeUSD Protocol Team\r\n * @notice Defines error types specific to SubVault operations\r\n * @dev Interface containing SubVault-specific error definitions\r\n */\r\ninterface ISubVaultErrors {\r\n    /**\r\n     * @notice Thrown when caller is not authorized\r\n     * @param caller Address of unauthorized caller\r\n     */\r\n    error UnauthorizedCaller(address caller);\r\n\r\n    /**\r\n     * @notice Thrown when asset operation is unsupported\r\n     * @param asset Address of unsupported asset\r\n     */\r\n    error UnsupportedAsset(address asset);\r\n\r\n    /**\r\n     * @notice Thrown when asset is already configured\r\n     * @param asset Address of already supported asset\r\n     */\r\n    error AssetAlreadySupported(address asset);\r\n\r\n    /**\r\n     * @notice Thrown when address is invalid (usually zero)\r\n     * @param addr The invalid address\r\n     */\r\n    error InvalidAddress(address addr);\r\n\r\n    /**\r\n     * @notice Thrown when amount is invalid (usually zero)\r\n     */\r\n    error InvalidAmount();\r\n\r\n    /**\r\n     * @notice Thrown when deposit operation fails\r\n     * @param reason Description of failure\r\n     */\r\n    error DepositFailed(string reason);\r\n\r\n    /**\r\n     * @notice Thrown when withdrawal operation fails\r\n     * @param reason Description of failure\r\n     */\r\n    error WithdrawFailed(string reason);\r\n\r\n    /**\r\n     * @notice Thrown when emergency delay period hasn't passed\r\n     */\r\n    error EmergencyDelayNotPassed();\r\n\r\n    /**\r\n     * @notice Thrown when emergency mode is active\r\n     * @param timestamp Time when emergency mode was enabled\r\n     */\r\n    error EmergencyModeEnabled(uint256 timestamp);\r\n\r\n    /**\r\n     * @notice Thrown when emergency mode is not active\r\n     */\r\n    error EmergencyModeNotEnabled();\r\n\r\n    /**\r\n     * @notice Thrown when balance is insufficient\r\n     * @param requested Amount requested\r\n     * @param available Amount available\r\n     */\r\n    error InsufficientBalance(uint256 requested, uint256 available);\r\n\r\n    /**\r\n     * @notice Thrown when approval operation fails\r\n     * @param asset Asset for which approval failed\r\n     * @param spender Address that was to be approved\r\n     */\r\n    error ApprovalFailed(address asset, address spender);\r\n\r\n    /**\r\n     * @notice Thrown when attempting to remove primary asset\r\n     */\r\n    error CannotRemovePrimaryAsset();\r\n\r\n    /**\r\n     * @notice Thrown when primary asset operation fails\r\n     * @param reason Description of failure\r\n     */\r\n    error PrimaryAssetOperationFailed(string reason);\r\n\r\n    /**\r\n     * @notice Thrown when secondary asset operation fails\r\n     * @param reason Description of failure\r\n     */\r\n    error SecondaryAssetOperationFailed(string reason);\r\n\r\n    /**\r\n     * @notice Thrown when usual not initialized\r\n     */\r\n    error NotInitialized();\r\n\r\n    /**\r\n     * @notice Thrown when array length mismatch\r\n     */\r\n    error ArrayLengthMismatch();\r\n\r\n    /**\r\n     * @notice Thrown when an asset is not supported\r\n     * @param asset The unsupported asset address\r\n     * @dev Asset validation error\r\n     */\r\n    error AssetNotSupported(address asset);\r\n\r\n    /**\r\n     * @notice Thrown when a non-zero balance is found on an asset\r\n     * @param asset The asset with a non-zero balance\r\n     * @param balance The non-zero balance amount\r\n     * @dev Balance validation error\r\n     */\r\n    error NonZeroBalance(address asset, uint256 balance);\r\n}\r\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.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 PausableUpgradeable is Initializable, ContextUpgradeable {\n    /// @custom:storage-location erc7201:openzeppelin.storage.Pausable\n    struct PausableStorage {\n        bool _paused;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Pausable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;\n\n    function _getPausableStorage() private pure returns (PausableStorage storage $) {\n        assembly {\n            $.slot := PausableStorageLocation\n        }\n    }\n\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    /**\n     * @dev The operation failed because the contract is paused.\n     */\n    error EnforcedPause();\n\n    /**\n     * @dev The operation failed because the contract is not paused.\n     */\n    error ExpectedPause();\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    function __Pausable_init() internal onlyInitializing {\n        __Pausable_init_unchained();\n    }\n\n    function __Pausable_init_unchained() internal onlyInitializing {\n        PausableStorage storage $ = _getPausableStorage();\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        PausableStorage storage $ = _getPausableStorage();\n        return $._paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        if (paused()) {\n            revert EnforcedPause();\n        }\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        if (!paused()) {\n            revert ExpectedPause();\n        }\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        PausableStorage storage $ = _getPausableStorage();\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        PausableStorage storage $ = _getPausableStorage();\n        $._paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"},{"file_path":"contracts/interfaces/access/IRegistry.sol","source_code":"// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.23;\r\n\r\n/**\r\n * @title Registry Interface\r\n * @author ZeUSD Protocol Team\r\n * @notice Interface for the main registry contract that manages protocol contract addresses\r\n * @dev All contract references in the protocol are managed through this registry\r\n */\r\ninterface IRegistry {\r\n    /**\r\n     * @notice Registers a new contract in the registry\r\n     * @param id Contract identifier\r\n     * @param addr Contract address\r\n     * @param version Contract version\r\n     */\r\n    function registerContract(bytes32 id, address addr, uint256 version) external;\r\n\r\n    /**\r\n     * @notice Updates an existing contract address\r\n     * @param id Contract identifier\r\n     * @param newAddr New contract address\r\n     * @param newVersion New version number\r\n     */\r\n    function updateContract(bytes32 id, address newAddr, uint256 newVersion) external;\r\n\r\n    /**\r\n     * @notice Retrieves a contract address\r\n     * @param id Contract identifier\r\n     * @return addr Contract address\r\n     */\r\n    function getContract(bytes32 id) external view returns (address addr);\r\n\r\n    /**\r\n     * @notice Gets contract details\r\n     * @param id Contract identifier\r\n     * @return addr Contract address\r\n     * @return version Contract version\r\n     * @return active Whether contract is active\r\n     */\r\n    function getContractInfo(\r\n        bytes32 id\r\n    ) external view returns (address addr, uint256 version, bool active);\r\n}\r\n"},{"file_path":"@openzeppelin/contracts/utils/StorageSlot.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(newImplementation.code.length > 0);\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    struct Int256Slot {\n        int256 value;\n    }\n\n    struct StringSlot {\n        string value;\n    }\n\n    struct BytesSlot {\n        bytes value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Int256Slot` with member `value` located at `slot`.\n     */\n    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `StringSlot` with member `value` located at `slot`.\n     */\n    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n     */\n    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BytesSlot` with member `value` located at `slot`.\n     */\n    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n     */\n    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n}\n"},{"file_path":"contracts/errors/ISystemErrors.sol","source_code":"// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.23;\r\n\r\n/**\r\n * @title System Errors Interface\r\n * @author ZeUSD Protocol Team\r\n * @notice Defines standard error types used across the protocol\r\n * @dev Interface containing common error definitions\r\n */\r\ninterface ISystemErrors {\r\n    /**\r\n     * @notice Error thrown for invalid address inputs\r\n     * @param addr The invalid address\r\n     */\r\n    error InvalidAddress(address addr);\r\n\r\n    /**\r\n     * @notice Error thrown for unauthorized operations\r\n     * @param message Error description\r\n     */\r\n    error Unauthorized(string message);\r\n\r\n    /**\r\n     * @notice Error thrown for invalid role operations\r\n     * @param role Role identifier that caused the error\r\n     */\r\n    error InvalidRole(bytes32 role);\r\n\r\n    /**\r\n     * @notice Error thrown for invalid configuration parameters\r\n     * @param message Error description\r\n     */\r\n    error InvalidConfig(string message);\r\n\r\n    /**\r\n     * @notice Error thrown when an operation fails\r\n     * @param message Error description\r\n     */\r\n    error OperationFailed(string message);\r\n\r\n    /**\r\n     * @notice Error thrown for invalid array lengths in batch operations\r\n     */\r\n    error InvalidArrayLength();\r\n\r\n    /**\r\n     * @notice Error thrown when router is not properly set\r\n     * @param message Error description\r\n     */\r\n    error RouterNotSet(string message);\r\n\r\n    /**\r\n     * @notice Error thrown when caller is not the router\r\n     * @param message Error description\r\n     */\r\n    error NotRouter(string message);\r\n\r\n    /**\r\n     * @notice Error thrown for initial approval issues\r\n     * @param message Error description\r\n     */\r\n    error InitialApproval(string message);\r\n\r\n    /**\r\n     * @notice Error thrown when contract not found in registry\r\n     * @param id Contract identifier\r\n     */\r\n    error ContractNotFound(bytes32 id);\r\n\r\n    /**\r\n     * @notice Error thrown when trying to grant a role to the zero address\r\n     */\r\n    error ZeroAddress();\r\n\r\n    /**\r\n     * @notice Error thrown when version doesn't match expected\r\n     * @param expected Expected version\r\n     * @param actual Actual version\r\n     */\r\n    error InvalidVersion(uint256 expected, uint256 actual);\r\n\r\n    /**\r\n     * @notice Error thrown when contract already exists in registry\r\n     * @param id Contract identifier\r\n     */\r\n    error ContractExists(bytes32 id);\r\n}\r\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"},{"file_path":"@openzeppelin/contracts/interfaces/draft-IERC6093.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard ERC-20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\n */\ninterface IERC20Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC20InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC20InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     * @param allowance Amount of tokens a `spender` is allowed to operate with.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC20InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC-721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\n */\ninterface IERC721Errors {\n    /**\n     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\n     * Used in balance queries.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721InvalidOwner(address owner);\n\n    /**\n     * @dev Indicates a `tokenId` whose `owner` is the zero address.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721NonexistentToken(uint256 tokenId);\n\n    /**\n     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param tokenId Identifier number of a token.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC721InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC721InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC721InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC-1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\n */\ninterface IERC1155Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC1155InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC1155InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC1155MissingApprovalForAll(address operator, address owner);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC1155InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC1155InvalidOperator(address operator);\n\n    /**\n     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n     * Used in batch transfers.\n     * @param idsLength Length of the array of token identifiers\n     * @param valuesLength Length of the array of token amounts\n     */\n    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC1822Proxiable} from \"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\";\nimport {ERC1967Utils} from \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol\";\nimport {Initializable} from \"./Initializable.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n */\nabstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {\n    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n    address private immutable __self = address(this);\n\n    /**\n     * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`\n     * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\n     * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.\n     * If the getter returns `\"5.0.0\"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must\n     * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\n     * during an upgrade.\n     */\n    string public constant UPGRADE_INTERFACE_VERSION = \"5.0.0\";\n\n    /**\n     * @dev The call is from an unauthorized context.\n     */\n    error UUPSUnauthorizedCallContext();\n\n    /**\n     * @dev The storage `slot` is unsupported as a UUID.\n     */\n    error UUPSUnsupportedProxiableUUID(bytes32 slot);\n\n    /**\n     * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n     * a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case\n     * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n     * function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n     * fail.\n     */\n    modifier onlyProxy() {\n        _checkProxy();\n        _;\n    }\n\n    /**\n     * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n     * callable on the implementing contract but not through proxies.\n     */\n    modifier notDelegated() {\n        _checkNotDelegated();\n        _;\n    }\n\n    function __UUPSUpgradeable_init() internal onlyInitializing {\n    }\n\n    function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the\n     * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n     */\n    function proxiableUUID() external view virtual notDelegated returns (bytes32) {\n        return ERC1967Utils.IMPLEMENTATION_SLOT;\n    }\n\n    /**\n     * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n     * encoded in `data`.\n     *\n     * Calls {_authorizeUpgrade}.\n     *\n     * Emits an {Upgraded} event.\n     *\n     * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n     */\n    function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\n        _authorizeUpgrade(newImplementation);\n        _upgradeToAndCallUUPS(newImplementation, data);\n    }\n\n    /**\n     * @dev Reverts if the execution is not performed via delegatecall or the execution\n     * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.\n     * See {_onlyProxy}.\n     */\n    function _checkProxy() internal view virtual {\n        if (\n            address(this) == __self || // Must be called through delegatecall\n            ERC1967Utils.getImplementation() != __self // Must be called through an active proxy\n        ) {\n            revert UUPSUnauthorizedCallContext();\n        }\n    }\n\n    /**\n     * @dev Reverts if the execution is performed via delegatecall.\n     * See {notDelegated}.\n     */\n    function _checkNotDelegated() internal view virtual {\n        if (address(this) != __self) {\n            // Must not be called through delegatecall\n            revert UUPSUnauthorizedCallContext();\n        }\n    }\n\n    /**\n     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n     * {upgradeToAndCall}.\n     *\n     * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n     *\n     * ```solidity\n     * function _authorizeUpgrade(address) internal onlyOwner {}\n     * ```\n     */\n    function _authorizeUpgrade(address newImplementation) internal virtual;\n\n    /**\n     * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.\n     *\n     * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value\n     * is expected to be the implementation slot in ERC-1967.\n     *\n     * Emits an {IERC1967-Upgraded} event.\n     */\n    function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {\n        try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n            if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {\n                revert UUPSUnsupportedProxiableUUID(slot);\n            }\n            ERC1967Utils.upgradeToAndCall(newImplementation, data);\n        } catch {\n            // The implementation is not UUPS\n            revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);\n        }\n    }\n}\n"},{"file_path":"contracts/libraries/DataTypes.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\r\npragma solidity 0.8.23;\r\n\r\n/// @title Data Types Library\r\n/// @notice Centralizes type definitions used across the protocol\r\n/// @dev Contains all shared data structures and enums for protocol-wide use\r\n/// @custom:security-contact paras@zoth.io\r\nlibrary DataTypes {\r\n    /// @notice Defines the type classification for tokens in the protocol\r\n    /// @dev Uses uint8 internally for gas optimization since enum is stored as uint8\r\n    /// @custom:usage Used for token classification and validation in deposit/withdrawal flows\r\n    enum TokenType {\r\n        /// @notice Represents non-stablecoin tokens (e.g., ETH, BTC)\r\n        /// @dev Value = 0, optimized for gas when checking non-stable status\r\n        NotStableCoin,\r\n        /// @notice Represents stablecoins (e.g., USDC, DAI)\r\n        /// @dev Value = 1, optimized for gas when checking stable status\r\n        StableCoin\r\n    }\r\n\r\n    /// @notice Configuration for supported assets\r\n    /// @dev Struct is packed to optimize gas usage\r\n    /// @param isSupported Whether the asset is currently supported\r\n    /// @param integrationType The type of integration used for this asset\r\n    /// @param tokenType Classification of the token (stable/non-stable)\r\n    struct AssetConfig {\r\n        bool isSupported;\r\n        string integrationType;\r\n        TokenType tokenType; // Added enum field\r\n    }\r\n\r\n    // /// @notice Stores information about user deposits\r\n    // /// @dev Struct ordering optimized for packing into storage slots\r\n    // /// @param depositId Unique identifier for this deposit\r\n    // /// @param asset Address of the deposited asset\r\n    // /// @param amount Amount of asset deposited\r\n    // /// @param zeusdMinted Amount of zeUSD minted for this deposit\r\n    // /// @param timestamp When the deposit was made\r\n    // /// @param subVault Address of the subvault holding the deposit\r\n    // /// @param integrationType Type of integration used for this deposit\r\n    // /// @param active Whether this deposit is still active\r\n    // /// @param isPrimary Indicates if this is a primary asset deposit\r\n    // /// @param tokenType Classification of the deposited token\r\n    // struct UserDeposit {\r\n    //     uint256 depositId;\r\n    //     address collateralAddress;\r\n    //     address asset;\r\n    //     uint256 amount;\r\n    //     uint256 zeusdMinted;\r\n    //     uint256 timestamp;\r\n    //     address subVault;\r\n    //     string integrationType;\r\n    //     bool active;\r\n    //     bool isPrimary;\r\n    //     TokenType tokenType; // Added enum field\r\n    // }\r\n\r\n    /// @notice Configuration for protocol integrations\r\n    /// @dev Uses mapping for efficient asset support lookups\r\n    /// @param subVault Address of the subvault\r\n    /// @param isActive Whether the integration is currently active\r\n    /// @param registeredAt When the integration was first registered\r\n    /// @param lastUpdated When the integration was last updated\r\n    /// @param supportedAssets Mapping of supported assets for this integration\r\n    struct Integration {\r\n        address subVault;\r\n        bool isActive;\r\n        uint256 registeredAt;\r\n        uint256 lastUpdated;\r\n        mapping(address => bool) supportedAssets;\r\n    }\r\n\r\n    /// @notice Detailed information about collateral assets\r\n    /// @dev Struct ordering optimized for packing into storage slots\r\n    /// @param integrationType Type of integration used\r\n    /// @param collateralAddress Address of the collateral token\r\n    /// @param subVaultAddress Address of the associated subvault\r\n    /// @param price Current price of the collateral\r\n    /// @param ltv Loan-to-Value ratio for the collateral\r\n    /// @param isActive Whether this collateral is currently active\r\n    /// @param registeredAt Timestamp of collateral registration\r\n    /// @param lastUpdatedAt Timestamp of last update\r\n    /// @param tokenType Classification of the collateral token\r\n    struct CollateralDetails {\r\n        string integrationType;\r\n        address collateralAddress;\r\n        address subVaultAddress;\r\n        uint256 price;\r\n        uint256 ltv;\r\n        bool isActive;\r\n        uint256 registeredAt;\r\n        uint256 lastUpdatedAt;\r\n        TokenType tokenType; // Added enum field\r\n    }\r\n\r\n    /// @notice Parameters for updating subvault configuration\r\n    /// @dev Boolean flags used to selectively update specific parameters\r\n    /// @param price New price value\r\n    /// @param ltv New LTV value\r\n    /// @param isActive New active status\r\n    /// @param updatePrice Whether to update the price\r\n    /// @param updateLTV Whether to update the LTV\r\n    /// @param updateActive Whether to update the active status\r\n    struct SubVaultUpdateParams {\r\n        uint256 price;\r\n        uint256 ltv;\r\n        bool isActive;\r\n        bool updatePrice;\r\n        bool updateLTV;\r\n        bool updateActive;\r\n    }\r\n\r\n    /// @notice Parameters for updating protocol addresses\r\n    /// @dev Used in updateAddresses function to specify which addresses to update\r\n    /// @param updateCollateralVault If true, update collateralVault address\r\n    /// @param updateZeusdToken If true, update zeusdToken address\r\n    /// @param updateLzAdapter If true, update lzAdapter address\r\n    /// @param collateralVault New collateral vault contract address (only used if updateCollateralVault is true)\r\n    /// @param zeusdToken New ZeUSD token contract address (only used if updateZeusdToken is true)\r\n    /// @param lzAdapter New LayerZero adapter contract address (only used if updateLzAdapter is true)\r\n    struct AddressUpdateParams {\r\n        bool updateCollateralVault;\r\n        bool updateZeusdToken;\r\n        bool updateLzAdapter;\r\n        address collateralVault;\r\n        address zeusdToken;\r\n        address lzAdapter;\r\n    }\r\n\r\n    /// @notice Parameters for updating user deposit configuration\r\n    /// @dev Boolean flags used to selectively update specific parameters\r\n    /// @param collateralAddress New collateral address value\r\n    /// @param asset New asset address value\r\n    /// @param amount New amount value for the deposit\r\n    /// @param zeusdMinted New minted ZeUSD value\r\n    /// @param active New active status\r\n    /// @param isPrimary New primary status flag\r\n    /// @param updateCollateralAddress Whether to update the collateral address\r\n    /// @param updateAsset Whether to update the asset address\r\n    /// @param updateAmount Whether to update the amount\r\n    /// @param updateZeusdMinted Whether to update the minted ZeUSD amount\r\n    /// @param updateActive Whether to update the active status\r\n    /// @param updateIsPrimary Whether to update the primary status\r\n    struct UserDepositUpdateParams {\r\n        address collateralAddress;\r\n        address asset;\r\n        uint256 amount;\r\n        uint256 zeusdMinted;\r\n        bool active;\r\n        bool isPrimary;\r\n        bool updateCollateralAddress;\r\n        bool updateAsset;\r\n        bool updateAmount;\r\n        bool updateZeusdMinted;\r\n        bool updateActive;\r\n        bool updateIsPrimary;\r\n    }\r\n\r\n    /// @notice Metadata for deposits\r\n    /// @dev Struct to store deposit-related information\r\n    /// @param issuer Original depositor\r\n    /// @param collateralAddress Address of the collateral\r\n    /// @param asset Address of the deposited asset\r\n    /// @param amount Amount of the deposit\r\n    /// @param zeusdMinted Amount of zeUSD minted for this deposit\r\n    /// @param depositTimestamp Timestamp of the deposit\r\n    /// @param collateralPrice Price of the collateral at the time of deposit\r\n    /// @param subVault Address of the subvault\r\n    /// @param integrationType Type of integration used for this deposit\r\n    /// @param tokenType Classification of the deposited token\r\n    /// @param tokenId NFT token ID representing this deposit\r\n    struct DepositMetadata {\r\n        address issuer; // Address of the depositor\r\n        address collateralAddress;\r\n        address asset; // Address of the deposited asset\r\n        uint256 amount; // Amount of asset deposited\r\n        uint256 zeusdMinted; // Amount of ZeUSD minted\r\n        uint256 depositTimestamp;\r\n        uint256 tokenId; // NFT token ID representing this deposit\r\n        uint256 collateralPrice; // Price at deposit time\r\n        address subVault;\r\n        string integrationType;\r\n        TokenType tokenType; // Type of token deposited\r\n    }\r\n\r\n    /// @notice Stores information about user deposits\r\n    /// @dev Struct ordering optimized for packing into storage slots\r\n    /// @param depositId Unique identifier for this deposit\r\n    /// @param asset Address of the deposited asset\r\n    /// @param amount Amount of asset deposited\r\n    /// @param zeusdMinted Amount of zeUSD minted for this deposit\r\n    /// @param timestamp When the deposit was made\r\n    /// @param subVault Address of the subvault holding the deposit\r\n    /// @param integrationType Type of integration used for this deposit\r\n    /// @param active Whether this deposit is still active\r\n    /// @param isPrimary Indicates if this is a primary asset deposit\r\n    /// @param tokenType Classification of the deposited token\r\n    struct UserDeposit {\r\n        uint256 depositId;\r\n        address collateralAddress;\r\n        address asset;\r\n        uint256 amount;\r\n        uint256 zeusdMinted;\r\n        uint256 timestamp;\r\n        address subVault;\r\n        string integrationType;\r\n        bool active;\r\n        bool isPrimary;\r\n        TokenType tokenType; // Added enum field\r\n    }\r\n\r\n    /// @notice Parameters for updating deposit metadata\r\n    /// @dev Boolean flags used to selectively update specific parameters\r\n    /// @param updateIssuer Whether to update the issuer address\r\n    /// @param issuer New issuer address\r\n    /// @param updateCollateralAddress Whether to update the collateral address\r\n    /// @param collateralAddress New collateral address\r\n    struct MetadataUpdateParams {\r\n        bool updateIssuer;\r\n        address issuer;\r\n        bool updateCollateralAddress;\r\n        address collateralAddress;\r\n        bool updateAsset;\r\n        address asset;\r\n        bool updateAmount;\r\n        uint256 amount;\r\n        bool updateZeusdMinted;\r\n        uint256 zeusdMinted;\r\n        bool updateDepositTimestamp;\r\n        uint256 depositTimestamp;\r\n        bool updateCollateralPrice;\r\n        uint256 collateralPrice;\r\n        bool updateSubVault;\r\n        address subVault;\r\n        bool updateIntegrationType;\r\n        string integrationType;\r\n        bool updateTokenType;\r\n        TokenType tokenType;\r\n    }\r\n}\r\n"},{"file_path":"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Storage of the initializable contract.\n     *\n     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n     * when using with upgradeable contracts.\n     *\n     * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n     */\n    struct InitializableStorage {\n        /**\n         * @dev Indicates that the contract has been initialized.\n         */\n        uint64 _initialized;\n        /**\n         * @dev Indicates that the contract is in the process of being initialized.\n         */\n        bool _initializing;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n    /**\n     * @dev The contract is already initialized.\n     */\n    error InvalidInitialization();\n\n    /**\n     * @dev The contract is not initializing.\n     */\n    error NotInitializing();\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint64 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n     * production.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        // Cache values to avoid duplicated sloads\n        bool isTopLevelCall = !$._initializing;\n        uint64 initialized = $._initialized;\n\n        // Allowed calls:\n        // - initialSetup: the contract is not in the initializing state and no previous version was\n        //                 initialized\n        // - construction: the contract is initialized at version 1 (no reininitialization) and the\n        //                 current contract is just being deployed\n        bool initialSetup = initialized == 0 && isTopLevelCall;\n        bool construction = initialized == 1 && address(this).code.length == 0;\n\n        if (!initialSetup && !construction) {\n            revert InvalidInitialization();\n        }\n        $._initialized = 1;\n        if (isTopLevelCall) {\n            $._initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            $._initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint64 version) {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing || $._initialized >= version) {\n            revert InvalidInitialization();\n        }\n        $._initialized = version;\n        $._initializing = true;\n        _;\n        $._initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        _checkInitializing();\n        _;\n    }\n\n    /**\n     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n     */\n    function _checkInitializing() internal view virtual {\n        if (!_isInitializing()) {\n            revert NotInitializing();\n        }\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing) {\n            revert InvalidInitialization();\n        }\n        if ($._initialized != type(uint64).max) {\n            $._initialized = type(uint64).max;\n            emit Initialized(type(uint64).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint64) {\n        return _getInitializableStorage()._initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _getInitializableStorage()._initializing;\n    }\n\n    /**\n     * @dev Returns a pointer to the storage namespace.\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n        assembly {\n            $.slot := INITIALIZABLE_STORAGE\n        }\n    }\n}\n"},{"file_path":"contracts/errors/ICollateralVaultErrors.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\r\npragma solidity 0.8.23;\r\n\r\n/**\r\n * @title Collateral Vault Errors Interface\r\n * @author ZeUSD Protocol Team\r\n * @notice Defines error types specific to CollateralVault operations\r\n * @dev Interface containing CollateralVault-specific error definitions\r\n */\r\ninterface ICollateralVaultErrors {\r\n    /**\r\n     * @notice Thrown when an unauthorized address attempts router operations\r\n     * @param caller Address attempting the operation\r\n     * @dev Used to protect router-only functions\r\n     */\r\n    error UnauthorizedRouter(address caller);\r\n\r\n    /**\r\n     * @notice Thrown when an invalid (usually zero) address is provided\r\n     * @param addr The invalid address\r\n     * @dev Basic input validation error\r\n     */\r\n    error InvalidAddress(address addr);\r\n\r\n    /**\r\n     * @notice Thrown when invalid parameters are provided\r\n     * @param message Descriptive error message\r\n     * @dev Used for general parameter validation failures\r\n     */\r\n    error InvalidParameters(string message);\r\n\r\n    /**\r\n     * @notice Thrown when an invalid price is provided (usually zero)\r\n     * @dev Price validation error\r\n     */\r\n    error InvalidPrice();\r\n\r\n    /**\r\n     * @notice Thrown when an invalid LTV value is provided\r\n     * @dev LTV must be between 0 and 100\r\n     */\r\n    error InvalidLTV();\r\n\r\n    /**\r\n     * @notice Thrown when attempting to register a duplicate subvault\r\n     * @param collateral Address of the collateral\r\n     * @param existingSubVault Address of the existing subvault\r\n     * @dev Prevents duplicate subvault registrations\r\n     */\r\n    error SubVaultAlreadyRegistered(address collateral, address existingSubVault);\r\n\r\n    /**\r\n     * @notice Thrown when an unsupported asset is used\r\n     * @param asset Address of the unsupported asset\r\n     * @dev Asset validation error\r\n     */\r\n    error AssetNotSupported(address asset);\r\n\r\n    /**\r\n     * @notice Thrown when attempting to use an inactive subvault\r\n     * @dev State validation error\r\n     */\r\n    error SubVaultNotActive();\r\n\r\n    /**\r\n     * @notice Thrown when an unauthorized subvault attempts an operation\r\n     * @param subVault Address of the unauthorized subvault\r\n     * @dev Subvault authorization error\r\n     */\r\n    error UnauthorizedSubVault(address subVault);\r\n\r\n    /**\r\n     * @notice Thrown when an invalid amount is provided\r\n     * @dev Amount validation error (usually zero)\r\n     */\r\n    error InvalidAmount();\r\n\r\n    /**\r\n     * @notice Thrown when a calculation results in overflow\r\n     * @dev Mathematical safety error\r\n     */\r\n    error CalculationOverflow();\r\n\r\n    /**\r\n     * @notice Thrown when a requested deposit cannot be found\r\n     * @param depositId ID of the missing deposit\r\n     * @dev Deposit lookup error\r\n     */\r\n    error DepositNotFound(uint256 depositId);\r\n\r\n    /**\r\n     * @notice Thrown when attempting to operate on an inactive deposit\r\n     * @dev Deposit state validation error\r\n     */\r\n    error DepositNotActive();\r\n}\r\n"},{"file_path":"contracts/events/ICollateralVaultEvents.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\r\npragma solidity 0.8.23;\r\n\r\nimport '../libraries/DataTypes.sol';\r\n\r\n/**\r\n * @title Collateral Vault Events Interface\r\n * @author ZeUSD Protocol Team\r\n * @notice Defines all events emitted by the CollateralVault contract\r\n * @dev Events are used for off-chain tracking and monitoring of vault activities\r\n */\r\ninterface ICollateralVaultEvents {\r\n    /**\r\n     * @notice Emitted when admin role is changed\r\n     * @param caller Address that initiated the admin change\r\n     * @param newAdmin Address of the new admin\r\n     * @dev Critical event for tracking administrative changes\r\n     */\r\n    event AdminChanged(address indexed caller, address indexed newAdmin);\r\n\r\n    /**\r\n     * @notice Emitted when router address is set\r\n     * @param router Address of the newly set router contract\r\n     * @dev Router can only be set once and is critical for deposit operations\r\n     */\r\n    event RouterSet(address indexed router);\r\n\r\n    /**\r\n     * @notice Emitted when a subvault is registered or updated\r\n     * @param collateralAddress Address of the collateral token being registered\r\n     * @param subVaultAddress Address of the subvault managing the collateral\r\n     * @param integrationType Type of integration (e.g., \"Aave\", \"Compound\")\r\n     * @param price Initial/updated price of the collateral\r\n     * @param ltv Initial/updated Loan-to-Value ratio\r\n     * @param isActive Whether the subvault is active\r\n     * @param tokenType Type classification of the collateral token\r\n     * @dev Used to track subvault registration and configuration changes\r\n     */\r\n    event SubVaultRegistered(\r\n        address indexed collateralAddress,\r\n        address indexed subVaultAddress,\r\n        string integrationType,\r\n        uint256 price,\r\n        uint256 ltv,\r\n        bool isActive,\r\n        DataTypes.TokenType tokenType\r\n    );\r\n\r\n    /**\r\n     * @notice Emitted when subvault configuration is updated\r\n     * @param collateralAddress Address of the collateral token\r\n     * @param subVaultAddress Address of the affected subvault\r\n     * @param price Updated price of the collateral\r\n     * @param ltv Updated Loan-to-Value ratio\r\n     * @param isActive Updated active status\r\n     * @dev Tracks changes to existing subvault configurations\r\n     */\r\n    event SubVaultUpdated(\r\n        address indexed collateralAddress,\r\n        address indexed subVaultAddress,\r\n        uint256 price,\r\n        uint256 ltv,\r\n        bool isActive\r\n    );\r\n\r\n    /**\r\n     * @notice Emitted when a subvault is removed from the system\r\n     * @param collateralAddress Address of the removed collateral token\r\n     * @param subVaultAddress Address of the removed subvault\r\n     * @dev Important for tracking decommissioned subvaults\r\n     */\r\n    event SubVaultRemoved(address indexed collateralAddress, address indexed subVaultAddress);\r\n\r\n    /**\r\n     * @notice Emitted when a new deposit is recorded\r\n     * @param user Address of the depositor\r\n     * @param asset Address of the deposited asset\r\n     * @param amount Amount of asset deposited\r\n     * @param depositId Unique identifier for the deposit\r\n     * @param subVault Address of the subvault processing the deposit\r\n     * @param integrationType Integration type used for the deposit\r\n     * @param isPrimary Whether this is a primary deposit\r\n     * @param mintAmount Amount of ZeUSD minted against this deposit\r\n     * @param tokenType Type classification of the deposited token\r\n     * @dev Comprehensive tracking of new deposits and their parameters\r\n     */\r\n    event DepositRecorded(\r\n        address indexed user,\r\n        address indexed asset,\r\n        uint256 amount,\r\n        uint256 depositId,\r\n        address subVault,\r\n        string integrationType,\r\n        bool isPrimary,\r\n        uint256 mintAmount,\r\n        DataTypes.TokenType tokenType\r\n    );\r\n\r\n    /**\r\n     * @notice Emitted when a deposit is deactivated\r\n     * @param user Address of the deposit owner\r\n     * @param depositId ID of the deactivated deposit\r\n     * @param asset Address of the deposited asset\r\n     * @param amount Original deposit amount\r\n     * @param mintedAmount Amount of ZeUSD that was minted\r\n     * @param subVault Address of the associated subvault\r\n     * @dev Tracks deposit deactivations and final state\r\n     */\r\n    event DepositDeactivated(\r\n        address indexed user,\r\n        uint256 indexed depositId,\r\n        address asset,\r\n        uint256 amount,\r\n        uint256 mintedAmount,\r\n        address subVault\r\n    );\r\n\r\n    /**\r\n     * @notice Emitted when a deposit record is permanently removed\r\n     * @param user Address of the deposit owner\r\n     * @param depositId ID of the removed deposit\r\n     * @param asset Address of the deposited asset\r\n     * @param amount Original deposit amount\r\n     * @param zeusdMinted Amount of ZeUSD that was minted\r\n     * @param subVault Address of the associated subvault\r\n     * @dev Tracks permanent removal of deposit records\r\n     */\r\n    event DepositRemoved(\r\n        address indexed user,\r\n        uint256 indexed depositId,\r\n        address asset,\r\n        uint256 amount,\r\n        uint256 zeusdMinted,\r\n        address subVault\r\n    );\r\n\r\n    /**\r\n     * @notice Emitted when a user deposit is updated\r\n     * @param user Address of the deposit owner\r\n     * @param depositId ID of the updated deposit\r\n     * @param collateralAddress Updated collateral address\r\n     * @param asset Updated asset address\r\n     * @param amount Updated amount\r\n     * @param zeusdMinted Updated ZeUSD minted amount\r\n     * @param active Updated active status\r\n     * @param isPrimary Updated primary status\r\n     * @dev Tracks changes to deposit parameters\r\n     */\r\n    event UserDepositUpdated(\r\n        address indexed user,\r\n        uint256 indexed depositId,\r\n        address collateralAddress,\r\n        address asset,\r\n        uint256 amount,\r\n        uint256 zeusdMinted,\r\n        bool active,\r\n        bool isPrimary\r\n    );\r\n\r\n    /**\r\n     * @notice Emitted when router address is updated\r\n     * @param newRouter Address of the new router\r\n     * @dev Tracks router address changes\r\n     */\r\n    event RouterUpdated(address indexed newRouter);\r\n}\r\n"},{"file_path":"contracts/events/ISubVaultEvents.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\r\npragma solidity 0.8.23;\r\n\r\n/**\r\n * @title SubVault Events Interface\r\n * @author ZeUSD Protocol Team\r\n * @notice Events emitted by subvault operations\r\n * @dev All events that can be emitted by SubVault\r\n */\r\ninterface ISubVaultEvents {\r\n    /**\r\n     * @notice Emitted when router address is set\r\n     * @param router Address of the newly set router contract\r\n     * @dev Router can only be set once and is critical for deposit operations\r\n     */\r\n    event RouterSet(address indexed router);\r\n\r\n    /**\r\n     * @notice Emitted when oracle is set for an asset\r\n     * @param asset Asset address\r\n     * @param oracle Oracle address\r\n     * @dev Price oracle configuration event\r\n     */\r\n    event AssetOracleSet(address indexed asset, address indexed oracle);\r\n\r\n    /**\r\n     * @notice Emitted when an asset is added to supported assets\r\n     * @param asset Address of added asset\r\n     * @param reason Reason for adding\r\n     * @dev Asset support tracking event\r\n     */\r\n    event AssetAdded(address indexed asset, string reason);\r\n\r\n    /**\r\n     * @notice Emitted when an asset is removed from supported assets\r\n     * @param asset Address of removed asset\r\n     * @param reason Reason for removal\r\n     * @dev Asset removal tracking event\r\n     */\r\n    event AssetRemoved(address indexed asset, string reason);\r\n\r\n    /**\r\n     * @notice Emitted when a deposit is processed\r\n     * @param user User who deposited\r\n     * @param asset Asset deposited\r\n     * @param amount Amount deposited\r\n     * @param shares Shares minted\r\n     * @dev Deposit tracking event\r\n     */\r\n    event DepositProcessed(\r\n        address indexed user,\r\n        address indexed asset,\r\n        uint256 amount,\r\n        uint256 shares\r\n    );\r\n\r\n    /**\r\n     * @notice Emitted when a withdrawal is processed\r\n     * @param user User who withdrew\r\n     * @param asset Asset withdrawn\r\n     * @param amount Amount withdrawn\r\n     * @dev Withdrawal tracking event\r\n     */\r\n    event WithdrawProcessed(address indexed user, address indexed asset, uint256 amount);\r\n\r\n    /**\r\n     * @notice Emitted when emergency withdrawal is executed\r\n     * @param asset Asset withdrawn\r\n     * @param to Recipient address\r\n     * @param amount Amount withdrawn\r\n     * @param reason Reason for withdrawal\r\n     * @dev Emergency operation tracking event\r\n     */\r\n    event EmergencyWithdrawalExecuted(\r\n        address indexed asset,\r\n        address indexed to,\r\n        uint256 amount,\r\n        string reason\r\n    );\r\n\r\n    /**\r\n     * @notice Emitted when emergency mode status changes\r\n     * @param timestamp Time of change\r\n     * @param enabled New status\r\n     * @dev Emergency state tracking event\r\n     */\r\n    event EmergencyModeSet(uint256 timestamp, bool enabled);\r\n\r\n    /**\r\n     * @notice Emitted when admin role changes\r\n     * @param oldAdmin Previous admin address\r\n     * @param newAdmin New admin address\r\n     * @dev Administrative change tracking event\r\n     */\r\n    event AdminChanged(address indexed oldAdmin, address indexed newAdmin);\r\n\r\n    /**\r\n     * @notice Emitted when approval is granted\r\n     * @param asset Asset approved\r\n     * @param spender Address approved to spend\r\n     * @param amount Amount approved\r\n     * @dev Asset approval tracking event\r\n     */\r\n    event ApprovalGranted(address indexed asset, address indexed spender, uint256 amount);\r\n\r\n    /**\r\n     * @notice Emitted when approval is revoked\r\n     * @param asset Asset for which approval was revoked\r\n     * @param spender Address whose approval was revoked\r\n     * @dev Asset approval revocation tracking event\r\n     */\r\n    event ApprovalRevoked(address indexed asset, address indexed spender);\r\n\r\n    /**\r\n     * @notice Emitted when primary asset operation occurs\r\n     * @param user User involved in operation\r\n     * @param amount Amount involved\r\n     * @param isDeposit Whether operation was deposit\r\n     * @dev Primary asset operation tracking event\r\n     */\r\n    event PrimaryAssetOperation(address indexed user, uint256 amount, bool isDeposit);\r\n\r\n    /**\r\n     * @notice Emitted when secondary asset operation occurs\r\n     * @param asset Secondary asset involved\r\n     * @param user User involved in operation\r\n     * @param amount Amount involved\r\n     * @param isDeposit Whether operation was deposit\r\n     * @dev Secondary asset operation tracking event\r\n     */\r\n    event SecondaryAssetOperation(\r\n        address indexed asset,\r\n        address indexed user,\r\n        uint256 amount,\r\n        bool isDeposit\r\n    );\r\n\r\n    /**\r\n     * @notice Emitted when stable whitelist status changes\r\n     * @param user Address that was affected\r\n     * @param status New whitelist status\r\n     */\r\n    event StableWhitelistStatusChanged(address indexed user, bool status);\r\n}\r\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"AssetNotSupported","type":"error"},{"inputs":[],"name":"CalculationOverflow","type":"error"},{"inputs":[],"name":"DepositNotActive","type":"error"},{"inputs":[{"internalType":"uint256","name":"depositId","type":"uint256"}],"name":"DepositNotFound","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidLTV","type":"error"},{"inputs":[{"internalType":"string","name":"message","type":"string"}],"name":"InvalidParameters","type":"error"},{"inputs":[],"name":"InvalidPrice","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"collateral","type":"address"},{"internalType":"address","name":"existingSubVault","type":"address"}],"name":"SubVaultAlreadyRegistered","type":"error"},{"inputs":[],"name":"SubVaultNotActive","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"inputs":[{"internalType":"string","name":"message","type":"string"}],"name":"Unauthorized","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"UnauthorizedRouter","type":"error"},{"inputs":[{"internalType":"address","name":"subVault","type":"address"}],"name":"UnauthorizedSubVault","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"depositId","type":"uint256"},{"indexed":false,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintedAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"subVault","type":"address"}],"name":"DepositDeactivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositId","type":"uint256"},{"indexed":false,"internalType":"address","name":"subVault","type":"address"},{"indexed":false,"internalType":"string","name":"integrationType","type":"string"},{"indexed":false,"internalType":"bool","name":"isPrimary","type":"bool"},{"indexed":false,"internalType":"uint256","name":"mintAmount","type":"uint256"},{"indexed":false,"internalType":"enum DataTypes.TokenType","name":"tokenType","type":"uint8"}],"name":"DepositRecorded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"depositId","type":"uint256"},{"indexed":false,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"zeusdMinted","type":"uint256"},{"indexed":false,"internalType":"address","name":"subVault","type":"address"}],"name":"DepositRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"router","type":"address"}],"name":"RouterSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newRouter","type":"address"}],"name":"RouterUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collateralAddress","type":"address"},{"indexed":true,"internalType":"address","name":"subVaultAddress","type":"address"},{"indexed":false,"internalType":"string","name":"integrationType","type":"string"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ltv","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isActive","type":"bool"},{"indexed":false,"internalType":"enum DataTypes.TokenType","name":"tokenType","type":"uint8"}],"name":"SubVaultRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collateralAddress","type":"address"},{"indexed":true,"internalType":"address","name":"subVaultAddress","type":"address"}],"name":"SubVaultRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collateralAddress","type":"address"},{"indexed":true,"internalType":"address","name":"subVaultAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ltv","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isActive","type":"bool"}],"name":"SubVaultUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"depositId","type":"uint256"},{"indexed":false,"internalType":"address","name":"collateralAddress","type":"address"},{"indexed":false,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"zeusdMinted","type":"uint256"},{"indexed":false,"internalType":"bool","name":"active","type":"bool"},{"indexed":false,"internalType":"bool","name":"isPrimary","type":"bool"}],"name":"UserDepositUpdated","type":"event"},{"inputs":[],"name":"STABLE_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accessController","outputs":[{"internalType":"contract IAccessController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collateralAddress","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"enum DataTypes.TokenType","name":"tokenType","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"calculateMintAmount","outputs":[{"internalType":"uint256","name":"mintAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"collateralDetails","outputs":[{"internalType":"string","name":"integrationType","type":"string"},{"internalType":"address","name":"collateralAddress","type":"address"},{"internalType":"address","name":"subVaultAddress","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"ltv","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint256","name":"registeredAt","type":"uint256"},{"internalType":"uint256","name":"lastUpdatedAt","type":"uint256"},{"internalType":"enum DataTypes.TokenType","name":"tokenType","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositNFT","outputs":[{"internalType":"contract IZeUSD_CDP","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getActiveSubVaults","outputs":[{"internalType":"address[]","name":"collaterals","type":"address[]"},{"components":[{"internalType":"string","name":"integrationType","type":"string"},{"internalType":"address","name":"collateralAddress","type":"address"},{"internalType":"address","name":"subVaultAddress","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"ltv","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint256","name":"registeredAt","type":"uint256"},{"internalType":"uint256","name":"lastUpdatedAt","type":"uint256"},{"internalType":"enum DataTypes.TokenType","name":"tokenType","type":"uint8"}],"internalType":"struct DataTypes.CollateralDetails[]","name":"details","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllSubVaults","outputs":[{"internalType":"address[]","name":"collaterals","type":"address[]"},{"components":[{"internalType":"string","name":"integrationType","type":"string"},{"internalType":"address","name":"collateralAddress","type":"address"},{"internalType":"address","name":"subVaultAddress","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"ltv","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint256","name":"registeredAt","type":"uint256"},{"internalType":"uint256","name":"lastUpdatedAt","type":"uint256"},{"internalType":"enum DataTypes.TokenType","name":"tokenType","type":"uint8"}],"internalType":"struct DataTypes.CollateralDetails[]","name":"details","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRegisteredCollaterals","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collateralAddress","type":"address"}],"name":"getSubVaultAddress","outputs":[{"internalType":"address","name":"subVaultAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSubVaultCounts","outputs":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"active","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collateralAddress","type":"address"}],"name":"getSubVaultDetails","outputs":[{"components":[{"internalType":"string","name":"integrationType","type":"string"},{"internalType":"address","name":"collateralAddress","type":"address"},{"internalType":"address","name":"subVaultAddress","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"ltv","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint256","name":"registeredAt","type":"uint256"},{"internalType":"uint256","name":"lastUpdatedAt","type":"uint256"},{"internalType":"enum DataTypes.TokenType","name":"tokenType","type":"uint8"}],"internalType":"struct DataTypes.CollateralDetails","name":"details","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"subVault","type":"address"}],"name":"getUserActivePositionsBySubVault","outputs":[{"components":[{"internalType":"address","name":"issuer","type":"address"},{"internalType":"address","name":"collateralAddress","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"zeusdMinted","type":"uint256"},{"internalType":"uint256","name":"depositTimestamp","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"collateralPrice","type":"uint256"},{"internalType":"address","name":"subVault","type":"address"},{"internalType":"string","name":"integrationType","type":"string"},{"internalType":"enum DataTypes.TokenType","name":"tokenType","type":"uint8"}],"internalType":"struct DataTypes.DepositMetadata[]","name":"metadata","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registryContract","type":"address"},{"internalType":"address","name":"_router","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"integrationType","type":"string"},{"internalType":"address","name":"collateralAddress","type":"address"},{"internalType":"address","name":"subVaultAddress","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"ltv","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"enum DataTypes.TokenType","name":"tokenType","type":"uint8"}],"name":"registerSubVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collateralAddress","type":"address"}],"name":"removeSubVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newRouter","type":"address"}],"name":"setRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collateralAddress","type":"address"},{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"ltv","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"updatePrice","type":"bool"},{"internalType":"bool","name":"updateLTV","type":"bool"},{"internalType":"bool","name":"updateActive","type":"bool"}],"internalType":"struct DataTypes.SubVaultUpdateParams","name":"params","type":"tuple"}],"name":"updateSubVaultConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"collateralAddress","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"validateAndPrepareDeposit","outputs":[{"components":[{"internalType":"address","name":"issuer","type":"address"},{"internalType":"address","name":"collateralAddress","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"zeusdMinted","type":"uint256"},{"internalType":"uint256","name":"depositTimestamp","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"collateralPrice","type":"uint256"},{"internalType":"address","name":"subVault","type":"address"},{"internalType":"string","name":"integrationType","type":"string"},{"internalType":"enum DataTypes.TokenType","name":"tokenType","type":"uint8"}],"internalType":"struct DataTypes.DepositMetadata","name":"metadata","type":"tuple"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":null}