| id | overview |
|---|---|
| title | Contract Overview |
| sidebar_position | 2 |
Detailed overview of the LifeCycle Cash Flow smart contract architecture and functions.
The LifeCycle Cash Flow contract manages payment distributions for tokenized securities on Hedera. It supports:
- Distribution Execution: Execute dividend or coupon payments to token holders
- Bond Cash-Outs: Execute bond maturity redemptions
- Snapshot Payments: Execute one-time payments based on token holder snapshots
- Payment Management: Manage payment tokens (USDC, HBAR, or other HTS tokens)
The contract uses OpenZeppelin's Upgradeable Contracts pattern:
- Proxy Pattern: Allows upgrading contract logic without changing address
- Storage Layout: Preserves state across upgrades
- Access Control: Role-based permissions for upgrade operations
The contract implements fine-grained access control:
- DEFAULT_ADMIN_ROLE: Full contract administration
- PAUSER_ROLE: Pause/unpause contract in emergencies
- PAYOUT_ROLE: Execute distributions and snapshots
- CASHOUT_ROLE: Execute bond cash-outs
- TRANSFERER_ROLE: Transfer payment tokens from contract
- PAYMENT_TOKEN_MANAGER_ROLE: Update payment token configuration
Execute dividend/coupon payments to a page of holders:
function executeDistribution(
address _asset,
uint256 _distributionID,
uint256 _pageIndex,
uint256 _pageLength
) external returns (
address[] memory failed,
address[] memory succeeded,
uint256[] memory paidAmount,
bool hasMore
)Parameters:
_asset: ATS token address_distributionID: Distribution ID from ATS contract_pageIndex: Starting index for pagination_pageLength: Number of holders to process
Returns:
failed: Addresses where payment failedsucceeded: Addresses where payment succeededpaidAmount: Amounts paid to each succeeded addresshasMore: True if more holders remain
Retry payments to specific addresses:
function executeDistributionByAddresses(
address _asset,
uint256 _distributionID,
address[] calldata _holders
) external returns (
address[] memory failed,
address[] memory succeeded,
uint256[] memory paidAmount
)Use case: Retry failed payments from paginated execution
Execute bond maturity redemption:
function executeBondCashOut(
address _bond,
uint256 _pageIndex,
uint256 _pageLength
) external returns (
address[] memory failed,
address[] memory succeeded,
uint256[] memory paidAmount,
bool hasMore
)Cash out bonds for specific holders:
function executeBondCashOutByAddresses(
address _bond,
address[] calldata _holders
) external returns (
address[] memory failed,
address[] memory succeeded,
uint256[] memory paidAmount
)Pay fixed amount distributed proportionally:
function executeAmountSnapshot(
address _asset,
uint256 _snapshotID,
uint256 _pageIndex,
uint256 _pageLength,
uint256 _amount
) external returns (
address[] memory failed,
address[] memory succeeded,
uint256[] memory paidAmount,
bool hasMore
)Parameters:
_amount: Total amount to distribute proportionally based on holdings
Example: Distribute $10,000 proportionally to all holders based on their token balance percentage
Pay percentage of contract balance:
function executePercentageSnapshot(
address _asset,
uint256 _snapshotID,
uint256 _pageIndex,
uint256 _pageLength,
uint256 _percentage
) external returns (
address[] memory failed,
address[] memory succeeded,
uint256[] memory paidAmount,
bool hasMore
)Parameters:
_percentage: Percentage of contract balance to distribute (in basis points, e.g., 1000 = 10%)
Example: Distribute 5% of contract's payment token balance to holders
Both snapshot types also have ByAddresses variants for retrying specific holders.
function getPaymentToken() external view returns (IERC20)Returns the current payment token address (e.g., USDC).
function getPaymentTokenDecimals() external view returns (uint8)Returns decimals of the payment token (e.g., 6 for USDC).
function updatePaymentToken(address paymentToken) externalRequires: PAYMENT_TOKEN_MANAGER_ROLE
Change the payment token used for distributions.
function transferPaymentToken(address to, uint256 amount) externalRequires: TRANSFERER_ROLE
Transfer payment tokens from contract to another address.
event DistributionExecuted(
uint256 distributionID,
uint256 pageIndex,
uint256 pageLength,
address[] failed,
address[] succeeded,
uint256[] paidAmount
)Emitted when a distribution page is executed.
event CashOutExecuted(
uint256 pageIndex,
uint256 pageLength,
address[] failed,
address[] succeeded,
uint256[] paidAmount
)Emitted when a bond cash-out page is executed.
event PaymentTokenChanged(address paymentToken)Emitted when payment token is updated.
For large holder lists, use pagination:
uint256 pageIndex = 0;
uint256 pageLength = 100;
bool hasMore = true;
while (hasMore) {
(
address[] memory failed,
address[] memory succeeded,
uint256[] memory paid,
bool more
) = contract.executeDistribution(asset, distributionID, pageIndex, pageLength);
hasMore = more;
pageIndex += pageLength;
// Process results...
}The contract integrates with ATS tokens:
- Distribution Data: Fetches distribution details from ATS contract
- Holder Lists: Retrieves token holders from ATS
- Balance Queries: Checks holder balances for proportional distribution
- Role-Based Access: Only authorized accounts can execute operations
- Pausability: Emergency pause for all operations
- Upgradeability: Fix bugs without redeploying
- Event Logging: Full audit trail of all operations
- Failure Tracking: Failed payments don't block successful ones
- Page Size: Recommended 50-100 holders per page
- Large Distributions: Use multiple transactions for >100 holders
- Failed Payments: Track and retry individually
- Test on Testnet: Always test full distribution flow before mainnet
- Monitor Events: Subscribe to contract events for real-time tracking
- Handle Failures: Implement retry logic for failed payments
- Check Balances: Ensure contract has sufficient payment tokens
- Use Pagination: Don't execute >100 holders in single transaction
- Contract Deployment - Deploy the contract
- SDK Integration - Use SDK to interact with contract
- Backend Integration - Backend integration patterns