73 lines
2.8 KiB
Solidity
73 lines
2.8 KiB
Solidity
// SPDX-License-Identifier: MIT
|
||
pragma solidity ^0.8.20;
|
||
|
||
/**
|
||
* @title MonetaryFormulas
|
||
* @notice Classical + GRU monetary formulas (canonical library — promoted from archive).
|
||
* @dev Formulas MUST match vault COMPLIANCE_REQUIREMENTS.md and GRU_Formulas.md crosswalk.
|
||
*
|
||
* Classical:
|
||
* - M = C + D; M = MB × m
|
||
* - V = PQ / M
|
||
* - m = 1 / r; m = (1 + c) / (r + c)
|
||
*
|
||
* GRU layer fan-out (policy): 1 M00 = 5 M0 = 25 M1 face units
|
||
*/
|
||
library MonetaryFormulas {
|
||
uint256 internal constant BP = 10_000;
|
||
uint256 internal constant WAD = 1e18;
|
||
|
||
/// @notice M = C + D
|
||
function moneySupplyCD(uint256 currency, uint256 deposits) internal pure returns (uint256) {
|
||
return currency + deposits;
|
||
}
|
||
|
||
/// @notice M = MB × m (m in 18 decimals)
|
||
function moneySupplyFromBase(uint256 monetaryBase, uint256 moneyMultiplierWad) internal pure returns (uint256) {
|
||
return (monetaryBase * moneyMultiplierWad) / WAD;
|
||
}
|
||
|
||
/// @notice V = PQ / M
|
||
function velocityPQOverM(uint256 priceLevel, uint256 quantity, uint256 moneySupply) internal pure returns (uint256) {
|
||
if (moneySupply == 0) return 0;
|
||
return (priceLevel * quantity) / moneySupply;
|
||
}
|
||
|
||
/// @notice m = 1 / r (r in basis points)
|
||
function simpleMultiplier(uint256 reserveRatioBps) internal pure returns (uint256) {
|
||
require(reserveRatioBps > 0 && reserveRatioBps <= BP, "MonetaryFormulas: r");
|
||
return (WAD * BP) / reserveRatioBps;
|
||
}
|
||
|
||
/// @notice m = (1 + c) / (r + c)
|
||
function multiplierWithCurrency(uint256 reserveRatioBps, uint256 currencyRatioBps) internal pure returns (uint256) {
|
||
require(reserveRatioBps > 0 && reserveRatioBps <= BP, "MonetaryFormulas: r");
|
||
require(currencyRatioBps <= BP, "MonetaryFormulas: c");
|
||
uint256 num = WAD * (BP + currencyRatioBps);
|
||
uint256 den = reserveRatioBps + currencyRatioBps;
|
||
require(den > 0, "MonetaryFormulas: den");
|
||
return num / den;
|
||
}
|
||
|
||
/// @notice Coverage ratio in bps: reserveValue / circulatingValue
|
||
function coverageRatioBps(uint256 reserveValue, uint256 circulatingValue) internal pure returns (uint256) {
|
||
if (circulatingValue == 0) return type(uint256).max;
|
||
return (reserveValue * BP) / circulatingValue;
|
||
}
|
||
|
||
/// @notice Effective GRU layer multiplier M00→M1 (25 face units per M00)
|
||
function gruM00ToM1Fanout() internal pure returns (uint256) {
|
||
return 25;
|
||
}
|
||
|
||
/// @notice 7:10 atomic issuance factor as WAD (10/7)
|
||
function gruAtomicIssuanceFactorWad() internal pure returns (uint256) {
|
||
return (10 * WAD) / 7;
|
||
}
|
||
|
||
/// @notice v_cov = v_adj × (coverageBps / 12000)
|
||
function coverageWeightedVelocity(uint256 vAdjWad, uint256 coverageBps) internal pure returns (uint256) {
|
||
return (vAdjWad * coverageBps) / 12_000;
|
||
}
|
||
}
|