AdvancedDistributionFacet
Inherits: AccessControl
Author: CMX Protocol Team
Diamond facet for advanced distribution waterfall calculations
*This facet handles complex distribution logic including:
Multiple waterfall models (American, European, Hybrid)
GP catchup calculations
Preferred return accrual over time
Hurdle rate logic
Distribution simulation and modeling Key Features:
American waterfall (deal-by-deal carry)
European waterfall (whole fund carry)
Hybrid waterfall models
Time-based preferred return accrual
GP catchup mechanisms
Hurdle rate thresholds
Distribution simulation
Performance analytics Waterfall Models:
American: GP gets carry on each profitable exit
European: GP gets carry only after all capital + preferred return
Hybrid: Custom combination of American and European*
State Variables
FUND_ROLE
Role for fund operations
bytes32 public constant FUND_ROLE = keccak256("FUND_ROLE");
OPERATOR_ROLE
Role for operators
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
GP_ROLE
Role for general partner
bytes32 public constant GP_ROLE = keccak256("GP_ROLE");
BASIS_POINTS
Basis points constant (10000 = 100%)
uint256 private constant BASIS_POINTS = 10000;
DAYS_PER_YEAR
Days per year for calculations
uint256 private constant DAYS_PER_YEAR = 365;
WATERFALL_AMERICAN
uint8 public constant WATERFALL_AMERICAN = 0;
WATERFALL_EUROPEAN
uint8 public constant WATERFALL_EUROPEAN = 1;
WATERFALL_HYBRID
uint8 public constant WATERFALL_HYBRID = 2;
DIST_RETURN_OF_CAPITAL
uint8 public constant DIST_RETURN_OF_CAPITAL = 0;
DIST_PREFERRED_RETURN
uint8 public constant DIST_PREFERRED_RETURN = 1;
DIST_GP_CATCHUP
uint8 public constant DIST_GP_CATCHUP = 2;
DIST_CARRIED_INTEREST
uint8 public constant DIST_CARRIED_INTEREST = 3;
DIST_RESIDUAL_PROFITS
uint8 public constant DIST_RESIDUAL_PROFITS = 4;
Functions
onlyFundOrGP
modifier onlyFundOrGP();
onlyOperatorOrGP
modifier onlyOperatorOrGP();
initializeDistributionConfig
Initialize the advanced distribution engine
Sets up distribution configuration and waterfall parameters
function initializeDistributionConfig(
uint8 model,
uint256 preferredReturnRate,
uint256 catchupPercentage,
uint256 carriedInterestSplit,
bool compoundPreferredReturn,
uint256 hurdleRate
) external onlyOperatorOrGP;
Parameters
model
uint8
Waterfall model (0=American, 1=European, 2=Hybrid)
preferredReturnRate
uint256
Annual preferred return rate in basis points
catchupPercentage
uint256
GP catchup percentage (e.g., 100 for 100%)
carriedInterestSplit
uint256
GP share after catchup (e.g., 20 for 20%)
compoundPreferredReturn
bool
Whether to compound preferred return
hurdleRate
uint256
Minimum return before carry (in basis points)
setDistributionConfig
Update distribution configuration
Updates the waterfall configuration parameters
function setDistributionConfig(
uint8 model,
uint256 preferredReturnRate,
uint256 catchupPercentage,
uint256 carriedInterestSplit,
bool compoundPreferredReturn,
uint256 hurdleRate
) external onlyOperatorOrGP;
Parameters
model
uint8
New waterfall model
preferredReturnRate
uint256
New preferred return rate
catchupPercentage
uint256
New catchup percentage
carriedInterestSplit
uint256
New carried interest split
compoundPreferredReturn
bool
Whether to compound preferred return
hurdleRate
uint256
New hurdle rate
calculateDistribution
Calculate distribution amounts without executing
Performs waterfall calculation based on current configuration
function calculateDistribution(uint256 totalAmount, bool isFinalDistribution)
external
view
returns (address[] memory recipients, uint256[] memory amounts, uint8[] memory distributionTypes);
Parameters
totalAmount
uint256
Total amount to distribute
isFinalDistribution
bool
Whether this is the final distribution
Returns
recipients
address[]
Array of recipient addresses
amounts
uint256[]
Array of distribution amounts
distributionTypes
uint8[]
Array of distribution types
executeDistribution
Execute a distribution with waterfall logic
Calculates and records distribution according to waterfall
function executeDistribution(uint256 totalAmount, bool isFinalDistribution)
external
onlyFundOrGP
returns (address[] memory recipients, uint256[] memory amounts, uint8[] memory distributionTypes);
Parameters
totalAmount
uint256
Total amount to distribute
isFinalDistribution
bool
Whether this is the final distribution
Returns
recipients
address[]
Array of recipient addresses
amounts
uint256[]
Array of distribution amounts
distributionTypes
uint8[]
Array of distribution types
accruePreferredReturn
Accrue preferred return for a period
Calculates and records preferred return accrual
function accruePreferredReturn(uint256 periodDays) external onlyFundOrGP;
Parameters
periodDays
uint256
Number of days to accrue
updateWaterfallState
Update waterfall state manually
Updates state for external contributions/distributions
function updateWaterfallState(uint256 contributions, uint256 distributions, uint8 distributionType)
external
onlyFundOrGP;
Parameters
contributions
uint256
New contributions
distributions
uint256
New distributions
distributionType
uint8
Type of distribution
getDistributionConfig
Get current distribution configuration
function getDistributionConfig() external view returns (UniversalFundStorage.DistributionConfig memory config);
Returns
config
UniversalFundStorage.DistributionConfig
Current distribution configuration
getWaterfallState
Get current waterfall state
function getWaterfallState() external view returns (UniversalFundStorage.WaterfallState memory state);
Returns
state
UniversalFundStorage.WaterfallState
Current waterfall state
calculateCarriedInterest
Calculate carried interest for a GP
function calculateCarriedInterest(uint256 profits, address gp) external view returns (uint256 carriedInterest);
Parameters
profits
uint256
Total profits
gp
address
GP address
Returns
carriedInterest
uint256
Carried interest amount
calculatePreferredReturn
Calculate preferred return for an investor over a period
function calculatePreferredReturn(address investor, uint256 periodDays)
external
view
returns (uint256 preferredReturn);
Parameters
investor
address
The investor address
periodDays
uint256
Number of days
Returns
preferredReturn
uint256
Preferred return amount
getRemainingPreferredReturn
Get remaining preferred return owed
function getRemainingPreferredReturn() external view returns (uint256 remaining);
Returns
remaining
uint256
Remaining preferred return amount
isHurdleRateAchieved
Check if hurdle rate has been achieved
function isHurdleRateAchieved() public view returns (bool achieved);
Returns
achieved
bool
True if hurdle rate is achieved
getNextDistributionType
Get the next distribution type in the waterfall
function getNextDistributionType() external view returns (uint8 distributionType);
Returns
distributionType
uint8
Next distribution type
simulateDistribution
Simulate a distribution without executing
function simulateDistribution(uint256 amount, bool isFinalDistribution)
external
view
returns (
uint256 capitalReturn,
uint256 preferredReturn,
uint256 gpCatchup,
uint256 carriedInterest,
uint256 residualProfits
);
Parameters
amount
uint256
Amount to distribute
isFinalDistribution
bool
Whether this is final distribution
Returns
capitalReturn
uint256
Amount going to capital return
preferredReturn
uint256
Amount going to preferred return
gpCatchup
uint256
Amount going to GP catchup
carriedInterest
uint256
Amount going to carried interest
residualProfits
uint256
Amount going to residual profits
_calculateDistribution
Internal distribution calculation with waterfall logic
function _calculateDistribution(uint256 totalAmount, bool isFinalDistribution)
internal
view
returns (address[] memory recipients, uint256[] memory amounts, uint8[] memory distributionTypes);
Parameters
totalAmount
uint256
Total amount to distribute
isFinalDistribution
bool
Whether this is final distribution
Returns
recipients
address[]
Array of recipient addresses
amounts
uint256[]
Array of distribution amounts
distributionTypes
uint8[]
Array of distribution types
_calculateCapitalReturn
Calculate capital return amount
function _calculateCapitalReturn(uint256 availableAmount) internal view returns (uint256 capitalReturn);
Parameters
availableAmount
uint256
Available amount for distribution
Returns
capitalReturn
uint256
Amount for capital return
_calculatePreferredReturn
Calculate preferred return amount
function _calculatePreferredReturn(uint256 availableAmount) internal view returns (uint256 preferredReturn);
Parameters
availableAmount
uint256
Available amount for distribution
Returns
preferredReturn
uint256
Amount for preferred return
_calculateGPCatchup
Calculate GP catchup amount
function _calculateGPCatchup(uint256 availableAmount) internal view returns (uint256 catchupAmount);
Parameters
availableAmount
uint256
Available amount for distribution
Returns
catchupAmount
uint256
Amount for GP catchup
_calculateTargetCatchup
Calculate target GP catchup amount
function _calculateTargetCatchup() internal view returns (uint256 targetCatchup);
Returns
targetCatchup
uint256
Target catchup amount
_distributeProRata
Distribute amount pro-rata among investors
function _distributeProRata(
address[] memory recipients,
uint256[] memory amounts,
uint8[] memory distributionTypes,
uint256 startIndex,
address[] memory investors,
uint256 amount,
uint8 distType
) internal view returns (uint256 nextIndex);
Parameters
recipients
address[]
Recipients array
amounts
uint256[]
Amounts array
distributionTypes
uint8[]
Distribution types array
startIndex
uint256
Starting index in arrays
investors
address[]
Array of investor addresses
amount
uint256
Amount to distribute
distType
uint8
Distribution type
Returns
nextIndex
uint256
Next available index in arrays
_distributePreferred
Distribute preferred return based on amounts owed
function _distributePreferred(
address[] memory recipients,
uint256[] memory amounts,
uint8[] memory distributionTypes,
uint256 startIndex,
address[] memory investors,
uint256 amount
) internal view returns (uint256 nextIndex);
Parameters
recipients
address[]
Recipients array
amounts
uint256[]
Amounts array
distributionTypes
uint8[]
Distribution types array
startIndex
uint256
Starting index in arrays
investors
address[]
Array of investor addresses
amount
uint256
Amount to distribute
Returns
nextIndex
uint256
Next available index in arrays
_distributeToGPs
Distribute amount to GPs
function _distributeToGPs(
address[] memory recipients,
uint256[] memory amounts,
uint8[] memory distributionTypes,
uint256 startIndex,
address[] memory gps,
uint256 amount,
uint8 distType
) internal pure returns (uint256 nextIndex);
Parameters
recipients
address[]
Recipients array
amounts
uint256[]
Amounts array
distributionTypes
uint8[]
Distribution types array
startIndex
uint256
Starting index in arrays
gps
address[]
Array of GP addresses
amount
uint256
Amount to distribute
distType
uint8
Distribution type
Returns
nextIndex
uint256
Next available index in arrays
Events
DistributionCalculated
Emitted when distribution is calculated
event DistributionCalculated(uint256 totalAmount, uint256 recipientCount);
DistributionExecuted
Emitted when distribution is executed
event DistributionExecuted(address indexed recipient, uint256 amount, uint8 distributionType);
PreferredReturnAccrued
Emitted when preferred return is accrued
event PreferredReturnAccrued(uint256 amount, uint256 totalAccrued);
CarriedInterestEarned
Emitted when carried interest is earned
event CarriedInterestEarned(address indexed gp, uint256 amount);
WaterfallModelUpdated
Emitted when waterfall model is updated
event WaterfallModelUpdated(uint8 oldModel, uint8 newModel);
HurdleRateAchieved
Emitted when hurdle rate is achieved
event HurdleRateAchieved(uint256 totalReturn, uint256 hurdleRate);
DistributionConfigUpdated
Emitted when distribution configuration is updated
event DistributionConfigUpdated(uint8 model, uint256 preferredReturnRate, uint256 carriedInterestSplit);
Errors
AdvancedDistributionFacet__InvalidAmount
error AdvancedDistributionFacet__InvalidAmount();
AdvancedDistributionFacet__InvalidPeriod
error AdvancedDistributionFacet__InvalidPeriod();
AdvancedDistributionFacet__ExcessivePreferredReturn
error AdvancedDistributionFacet__ExcessivePreferredReturn();
AdvancedDistributionFacet__ExcessiveCarry
error AdvancedDistributionFacet__ExcessiveCarry();
AdvancedDistributionFacet__NotGP
error AdvancedDistributionFacet__NotGP();
AdvancedDistributionFacet__Unauthorized
error AdvancedDistributionFacet__Unauthorized();
AdvancedDistributionFacet__InvalidModel
error AdvancedDistributionFacet__InvalidModel();
Last updated
Was this helpful?