// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** * @title GRUConstants * @notice Constants and utilities for Global Reserve Unit (GRU) * @dev GRU is a NON-ISO 4217 synthetic unit of account, NOT legal tender * * MANDATORY COMPLIANCE: * - GRU SHALL NOT be treated as fiat currency * - GRU SHALL be explicitly identified as synthetic unit of account * - All GRU triangulations MUST be conducted through XAU * - GRU relationships MUST be enforced exactly: 1 M00 GRU = 5 M0 GRU = 25 M1 GRU */ library GRUConstants { /** * @notice GRU is NOT an ISO 4217 currency * @dev This constant explicitly identifies GRU as non-ISO */ string public constant GRU_CURRENCY_CODE = "GRU"; // Non-ISO 4217 synthetic unit of account /** * @notice GRU monetary layers */ string public constant GRU_M00 = "M00"; // Base layer (non-ISO) string public constant GRU_M0 = "M0"; // Collateral layer (non-ISO) string public constant GRU_M1 = "M1"; // Credit layer (non-ISO) /** * @notice GRU conversion ratios (MANDATORY - must be enforced exactly) * @dev 1 M00 GRU = 5 M0 GRU = 25 M1 GRU */ uint256 public constant M00_TO_M0_RATIO = 5; // 1 M00 = 5 M0 uint256 public constant M00_TO_M1_RATIO = 25; // 1 M00 = 25 M1 uint256 public constant M0_TO_M1_RATIO = 5; // 1 M0 = 5 M1 /** * @notice Decimals for GRU calculations (18 decimals for precision) */ uint256 public constant GRU_DECIMALS = 1e18; /** * @notice Convert M00 GRU to M0 GRU * @param m00Amount Amount in M00 GRU (18 decimals) * @return m0Amount Amount in M0 GRU (18 decimals) */ function m00ToM0(uint256 m00Amount) internal pure returns (uint256 m0Amount) { return (m00Amount * M00_TO_M0_RATIO * GRU_DECIMALS) / GRU_DECIMALS; } /** * @notice Convert M00 GRU to M1 GRU * @param m00Amount Amount in M00 GRU (18 decimals) * @return m1Amount Amount in M1 GRU (18 decimals) */ function m00ToM1(uint256 m00Amount) internal pure returns (uint256 m1Amount) { return (m00Amount * M00_TO_M1_RATIO * GRU_DECIMALS) / GRU_DECIMALS; } /** * @notice Convert M0 GRU to M1 GRU * @param m0Amount Amount in M0 GRU (18 decimals) * @return m1Amount Amount in M1 GRU (18 decimals) */ function m0ToM1(uint256 m0Amount) internal pure returns (uint256 m1Amount) { return (m0Amount * M0_TO_M1_RATIO * GRU_DECIMALS) / GRU_DECIMALS; } /** * @notice Convert M0 GRU to M00 GRU * @param m0Amount Amount in M0 GRU (18 decimals) * @return m00Amount Amount in M00 GRU (18 decimals) */ function m0ToM00(uint256 m0Amount) internal pure returns (uint256 m00Amount) { return (m0Amount * GRU_DECIMALS) / (M00_TO_M0_RATIO * GRU_DECIMALS); } /** * @notice Convert M1 GRU to M00 GRU * @param m1Amount Amount in M1 GRU (18 decimals) * @return m00Amount Amount in M00 GRU (18 decimals) */ function m1ToM00(uint256 m1Amount) internal pure returns (uint256 m00Amount) { return (m1Amount * GRU_DECIMALS) / (M00_TO_M1_RATIO * GRU_DECIMALS); } /** * @notice Convert M1 GRU to M0 GRU * @param m1Amount Amount in M1 GRU (18 decimals) * @return m0Amount Amount in M0 GRU (18 decimals) */ function m1ToM0(uint256 m1Amount) internal pure returns (uint256 m0Amount) { return (m1Amount * GRU_DECIMALS) / (M0_TO_M1_RATIO * GRU_DECIMALS); } /** * @notice Validate GRU layer code * @param layerCode Layer code to validate * @return isValid True if valid GRU layer */ function isValidGRULayer(string memory layerCode) internal pure returns (bool isValid) { bytes32 codeHash = keccak256(bytes(layerCode)); return codeHash == keccak256(bytes(GRU_M00)) || codeHash == keccak256(bytes(GRU_M0)) || codeHash == keccak256(bytes(GRU_M1)) || codeHash == keccak256(bytes(GRU_CURRENCY_CODE)); } }