From d1cc01b37bd3b77e96fa750281ca973a9c5d757d Mon Sep 17 00:00:00 2001 From: truthixify Date: Sun, 10 Aug 2025 00:20:16 +0100 Subject: [PATCH] added full documentation to the disbursement component --- src/components/disbursement.cairo | 96 ++++++++++++++++++++ src/interfaces/idisbursement.cairo | 138 +++++++++++++++++++++++++++++ 2 files changed, 234 insertions(+) diff --git a/src/components/disbursement.cairo b/src/components/disbursement.cairo index 0f1e0d9..6b8b344 100644 --- a/src/components/disbursement.cairo +++ b/src/components/disbursement.cairo @@ -1,3 +1,13 @@ +/// ## A Starknet component for managing payroll and disbursement schedules. +/// +/// This component handles the logic for: +/// - Creating, pausing, and resuming payment schedules. +/// - Storing a history of past schedules. +/// - Calculating individual member payments based on base pay and a weighted share of bonuses. +/// - Tracking the timing of disbursement cycles. +/// +/// It is intended to be integrated into a `Core` contract to manage an organization's payroll +/// system. #[starknet::component] pub mod DisbursementComponent { use littlefinger::interfaces::idisbursement::IDisbursement; @@ -10,23 +20,41 @@ pub mod DisbursementComponent { }; use starknet::{ContractAddress, get_block_timestamp, get_caller_address}; + /// Defines the storage layout for the `DisbursementComponent`. #[storage] pub struct Storage { + /// Maps an address to a boolean indicating if it is authorized to call privileged + /// functions. authorized_callers: Map, + /// The address of the component's owner. owner: ContractAddress, + /// Maps a schedule ID to an archived `DisbursementSchedule`. previous_schedules: Map, // only one active schedule at a time + /// The currently active disbursement schedule for the organization. current_schedule: DisbursementSchedule, + /// Maps a disbursement ID to a `UnitDisbursement` struct for tracking failed payments. failed_disbursements: Map< u256, UnitDisbursement, >, //map disbursement id to a failed disbursement + /// A counter for the total number of schedules created. schedules_count: u64, } + /// # DisbursementManager + /// + /// Public-facing implementation of the `IDisbursement` interface. #[embeddable_as(DisbursementManager)] pub impl DisbursementImpl< TContractState, +HasComponent //, +Drop, //impl Member: MemberManagerComponent::HasComponent, > of IDisbursement> { + /// Creates and activates a new disbursement schedule. + /// + /// ### Parameters + /// - `schedule_type`: Type of schedule (0: Recurring, 1: One-Time). + /// - `start`: Unix timestamp for the schedule's start time. + /// - `end`: Unix timestamp for the schedule's end time. + /// - `interval`: Payout interval in seconds. fn create_disbursement_schedule( ref self: ComponentState, schedule_type: u8, @@ -57,6 +85,7 @@ pub mod DisbursementComponent { self.current_schedule.write(new_disbursement_schedule); } + /// Pauses the currently active disbursement schedule. fn pause_disbursement(ref self: ComponentState) { self._assert_caller(); let mut disbursement_schedule = self.current_schedule.read(); @@ -68,6 +97,7 @@ pub mod DisbursementComponent { self.current_schedule.write(disbursement_schedule); } + /// Resumes a paused disbursement schedule. fn resume_schedule(ref self: ComponentState) { self._assert_caller(); let mut disbursement_schedule = self.current_schedule.read(); @@ -91,6 +121,10 @@ pub mod DisbursementComponent { // true // } + /// Updates the `last_execution` timestamp for the active schedule. + /// + /// ### Parameters + /// - `timestamp`: The Unix timestamp of the last successful execution. fn update_current_schedule_last_execution( ref self: ComponentState, timestamp: u64, ) { @@ -100,6 +134,10 @@ pub mod DisbursementComponent { self.current_schedule.write(current_schedule); } + /// Sets an archived schedule as the new active one. + /// + /// ### Parameters + /// - `schedule_id`: The ID of the schedule to activate. fn set_current_schedule(ref self: ComponentState, schedule_id: u64) { self._assert_caller(); let schedule = self.previous_schedules.entry(schedule_id).read(); @@ -107,12 +145,20 @@ pub mod DisbursementComponent { self.current_schedule.write(schedule); } + /// Returns the details of the currently active schedule. + /// + /// ### Returns + /// - `DisbursementSchedule`: A struct containing the active schedule's details. fn get_current_schedule(self: @ComponentState) -> DisbursementSchedule { let disbursement_schedule = self.current_schedule.read(); assert(disbursement_schedule != Default::default(), 'No schedule set'); disbursement_schedule } + /// Returns a list of all historical and current schedules. + /// + /// ### Returns + /// - `Array`: An array of all non-deleted schedules. fn get_disbursement_schedules( self: @ComponentState, ) -> Array { @@ -131,6 +177,15 @@ pub mod DisbursementComponent { disbursement_schedules_array } + /// Calculates the total payment for a member for one cycle. + /// + /// ### Parameters + /// - `member`: The details of the member. + /// - `total_bonus_available`: The total bonus pool for the cycle. + /// - `total_members_weight`: The sum of role weights for all members. + /// + /// ### Returns + /// - `u256`: The calculated total remuneration. fn compute_renumeration( ref self: ComponentState, member: MemberResponse, @@ -145,6 +200,11 @@ pub mod DisbursementComponent { renumeration } + /// Updates the payout interval for an existing schedule. + /// + /// ### Parameters + /// - `schedule_id`: The ID of the schedule to modify. + /// - `new_interval`: The new interval in seconds. fn update_schedule_interval( ref self: ComponentState, schedule_id: u64, new_interval: u64, ) { @@ -157,6 +217,11 @@ pub mod DisbursementComponent { self.previous_schedules.entry(schedule_id).write(disbursement_schedule); } + /// Updates the type (Recurring/One-Time) for an existing schedule. + /// + /// ### Parameters + /// - `schedule_id`: The ID of the schedule to modify. + /// - `schedule_type`: The new schedule type. fn update_schedule_type( ref self: ComponentState, schedule_id: u64, schedule_type: ScheduleType, ) { @@ -169,10 +234,18 @@ pub mod DisbursementComponent { self.previous_schedules.entry(schedule_id).write(disbursement_schedule); } + /// Returns the timestamp of the last payout for the active schedule. + /// + /// ### Returns + /// - `u64`: The Unix timestamp of the last execution. fn get_last_disburse_time(self: @ComponentState) -> u64 { self.current_schedule.read().last_execution } + /// Calculates the timestamp for the next expected payout. + /// + /// ### Returns + /// - `u64`: The Unix timestamp of the next disbursement. fn get_next_disburse_time(self: @ComponentState) -> u64 { let current_schedule = self.current_schedule.read(); let now = get_block_timestamp(); @@ -186,15 +259,23 @@ pub mod DisbursementComponent { } } + /// # InternalImpl + /// + /// Internal functions for initialization and privileged operations. #[generate_trait] pub impl InternalImpl< TContractState, +HasComponent, > of InternalTrait { + /// Grants another address permission to call privileged functions. + /// + /// ### Parameters + /// - `user`: The address to authorize. fn _add_authorized_caller(ref self: ComponentState, user: ContractAddress) { self._assert_caller(); self.authorized_callers.entry(user).write(true); } + /// Asserts that the function caller is authorized. Reverts if not. fn _assert_caller(ref self: ComponentState) { let caller = get_caller_address(); assert( @@ -203,6 +284,10 @@ pub mod DisbursementComponent { ); } + /// Marks a schedule as deleted. + /// + /// ### Parameters + /// - `schedule_id`: The ID of the schedule to delete. fn _delete_schedule(ref self: ComponentState, schedule_id: u64) { self._assert_caller(); let mut disbursement_schedule = self.current_schedule.read(); @@ -213,6 +298,13 @@ pub mod DisbursementComponent { self.current_schedule.write(disbursement_schedule); } + /// Initializes the first disbursement schedule for the component. + /// + /// ### Parameters + /// - `schedule_type`: Type of schedule (0: Recurring, 1: One-Time). + /// - `start`: Unix timestamp for the schedule's start time. + /// - `end`: Unix timestamp for the schedule's end time. + /// - `interval`: Payout interval in seconds. fn _initialize( ref self: ComponentState, schedule_type: u8, @@ -240,6 +332,10 @@ pub mod DisbursementComponent { self.current_schedule.write(disbursement_schedule); } + /// Initializes the component's basic state, setting the owner. + /// + /// ### Parameters + /// - `owner`: The address of the owner. fn _init(ref self: ComponentState, owner: ContractAddress) { self.owner.write(owner); self.authorized_callers.entry(owner).write(true); diff --git a/src/interfaces/idisbursement.cairo b/src/interfaces/idisbursement.cairo index 084bfc8..0e982fa 100644 --- a/src/interfaces/idisbursement.cairo +++ b/src/interfaces/idisbursement.cairo @@ -4,9 +4,30 @@ use littlefinger::structs::member_structs::MemberResponse; // TODO: The component should store failed disbursements, and everytime it disburses, after writing // to the storage make it retry +/// # IDisbursement +/// +/// This trait defines the public interface for a disbursement component. It outlines the +/// core functionalities for managing payment schedules for an organization, including their +/// creation, modification, and lifecycle management (pausing, resuming). It also specifies +/// how to calculate member remuneration based on their role and available bonuses. This interface +/// is designed to be implemented by a Starknet component that handles all payroll and +/// disbursement logic. #[starknet::interface] pub trait IDisbursement { // disbursement schedule handling + + /// # create_disbursement_schedule + /// + /// Creates a new disbursement schedule for the organization. + /// + /// ## Parameters + /// + /// - `ref self: T`: The current state of the contract. + /// - `schedule_type`: A numerical value representing the schedule type (0: Recurring, 1: + /// One-Time). + /// - `start`: The Unix timestamp when the schedule becomes active. + /// - `end`: The Unix timestamp when the schedule expires. + /// - `interval`: The duration in seconds between each payout execution. fn create_disbursement_schedule( ref self: T, schedule_type: u8, //schedule_id: felt252, @@ -14,10 +35,50 @@ pub trait IDisbursement { end: u64, interval: u64, ); + + /// # pause_disbursement + /// + /// Temporarily pauses the currently active disbursement schedule. + /// + /// ## Parameters + /// + /// - `ref self: T`: The current state of the contract. fn pause_disbursement(ref self: T); + + /// # resume_schedule + /// + /// Resumes a previously paused disbursement schedule. + /// + /// ## Parameters + /// + /// - `ref self: T`: The current state of the contract. fn resume_schedule(ref self: T); // fn delete_schedule(ref self: T,); + + /// # get_current_schedule + /// + /// Retrieves the details of the currently active disbursement schedule. + /// + /// ## Parameters + /// + /// - `self: @T`: A snapshot of the contract's state. + /// + /// ## Returns + /// + /// A `DisbursementSchedule` struct with the active schedule's details. fn get_current_schedule(self: @T) -> DisbursementSchedule; + + /// # get_disbursement_schedules + /// + /// Retrieves a list of all non-deleted disbursement schedules, including the active one. + /// + /// ## Parameters + /// + /// - `self: @T`: A snapshot of the contract's state. + /// + /// ## Returns + /// + /// An `Array` containing all relevant schedules. fn get_disbursement_schedules(self: @T) -> Array; // fn retry_failed_disbursement(ref self: T, schedule_id: u64); @@ -26,20 +87,97 @@ pub trait IDisbursement { // ref self: T, member: Member, disbursement_id: u256, timestamp: u64, caller: // ContractAddress, // ) -> bool; + + /// # update_current_schedule_last_execution + /// + /// Updates the last execution timestamp of the active schedule. + /// + /// ## Parameters + /// + /// - `ref self: T`: The current state of the contract. + /// - `timestamp`: The Unix timestamp of the last execution. fn update_current_schedule_last_execution(ref self: T, timestamp: u64); + + /// # set_current_schedule + /// + /// Sets a previously created schedule from the archives as the new active schedule. + /// + /// ## Parameters + /// + /// - `ref self: T`: The current state of the contract. + /// - `schedule_id`: The ID of the schedule to make active. fn set_current_schedule(ref self: T, schedule_id: u64); // Total members' weight is calculated by adding the weight of all members. // It can be a storage variable in the member module to make it easier to handle, concerning gas // for loop transactions + + /// # compute_renumeration + /// + /// Calculates a single member's total pay for a cycle. + /// + /// ## Parameters + /// + /// - `ref self: T`: The current state of the contract. + /// - `member`: The `MemberResponse` struct of the member. + /// - `total_bonus_available`: The total amount in the bonus pool for the cycle. + /// - `total_members_weight`: The sum of the role weights of all members. + /// + /// ## Returns + /// + /// The total remuneration amount for the member as a `u256`. fn compute_renumeration( ref self: T, member: MemberResponse, total_bonus_available: u256, total_members_weight: u16, // total_funds_available: u256, ) -> u256; // fn disburse(ref self: T, recipients: Array, token: ContractAddress); + + /// # update_schedule_interval + /// + /// Modifies the payment interval of a specific, existing schedule. + /// + /// ## Parameters + /// + /// - `ref self: T`: The current state of the contract. + /// - `schedule_id`: The ID of the schedule to update. + /// - `new_interval`: The new interval duration in seconds. fn update_schedule_interval(ref self: T, schedule_id: u64, new_interval: u64); + + /// # update_schedule_type + /// + /// Modifies the type of a specific, existing schedule. + /// + /// ## Parameters + /// + /// - `ref self: T`: The current state of the contract. + /// - `schedule_id`: The ID of the schedule to update. + /// - `schedule_type`: The new `ScheduleType` enum. fn update_schedule_type(ref self: T, schedule_id: u64, schedule_type: ScheduleType); + + /// # get_last_disburse_time + /// + /// Retrieves the timestamp of the last successful disbursement for the active schedule. + /// + /// ## Parameters + /// + /// - `self: @T`: A snapshot of the contract's state. + /// + /// ## Returns + /// + /// The Unix timestamp of the last execution as a `u64`. fn get_last_disburse_time(self: @T) -> u64; + + /// # get_next_disburse_time + /// + /// Calculates and returns the timestamp for the next scheduled disbursement. + /// + /// ## Parameters + /// + /// - `self: @T`: A snapshot of the contract's state. + /// + /// ## Returns + /// + /// The Unix timestamp of the next expected execution as a `u64`. fn get_next_disburse_time(self: @T) -> u64; }