The time-based release schedules feature enables vesting and milestone-based payouts for both bounty escrow and program escrow contracts. This allows funds to be released automatically or manually at specific intervals.
- ✅ Time-based vesting with specific release timestamps
- ✅ Automatic releases (anyone can trigger after timestamp)
- ✅ Manual releases (admin/authorized key can trigger anytime)
- ✅ Multiple schedules per bounty/program
- ✅ Complete audit trail with release history
- ✅ Event emission for all operations
- ✅ Comprehensive view functions for querying schedules
// Admin creates a vesting schedule for a bounty
contract.create_release_schedule(
&bounty_id, // u64: Bounty identifier
&amount, // i128: Amount to release (in smallest token unit)
&release_timestamp, // u64: Unix timestamp when release becomes available
&recipient_address, // Address: Who receives the funds
);// Anyone can trigger automatic release after timestamp
contract.release_schedule_automatic(
&bounty_id, // u64: Bounty identifier
&schedule_id, // u64: Schedule identifier
);// Admin can release anytime, even before timestamp
contract.release_schedule_manual(
&bounty_id, // u64: Bounty identifier
&schedule_id, // u64: Schedule identifier
);// Get specific schedule
let schedule = contract.get_release_schedule(&bounty_id, &schedule_id);
// Get all schedules for a bounty
let all_schedules = contract.get_all_release_schedules(&bounty_id);
// Get pending (unreleased) schedules
let pending = contract.get_pending_schedules(&bounty_id);
// Get schedules ready for automatic release
let due = contract.get_due_schedules(&bounty_id);
// Get complete release history
let history = contract.get_release_history(&bounty_id);// Authorized payout key creates a vesting schedule
contract.create_program_release_schedule(
&program_id, // String: Program identifier
&amount, // i128: Amount to release
&release_timestamp, // u64: Unix timestamp
&recipient_address, // Address: Winner/participant
);// Anyone can trigger automatic release after timestamp
contract.release_prog_schedule_automatic(
&program_id, // String: Program identifier
&schedule_id, // u64: Schedule identifier
);// Authorized key can release anytime
contract.release_prog_schedule_manual(
&program_id, // String: Program identifier
&schedule_id, // u64: Schedule identifier
);// Get specific program schedule
let schedule = contract.get_program_release_schedule(&program_id, &schedule_id);
// Get all schedules for a program
let all_schedules = contract.get_all_prog_release_schedules(&program_id);
// Get pending schedules
let pending = contract.get_pending_program_schedules(&program_id);
// Get schedules ready for automatic release
let due = contract.get_due_program_schedules(&program_id);
// Get complete release history
let history = contract.get_program_release_history(&program_id);Bounty Escrow:
ScheduleCreated {
bounty_id: u64,
schedule_id: u64,
amount: i128,
release_timestamp: u64,
recipient: Address,
created_by: Address,
}Program Escrow:
ProgramScheduleCreated {
program_id: String,
schedule_id: u64,
amount: i128,
release_timestamp: u64,
recipient: Address,
created_by: Address,
}Bounty Escrow:
ScheduleReleased {
bounty_id: u64,
schedule_id: u64,
amount: i128,
recipient: Address,
released_at: u64,
released_by: Address,
release_type: ReleaseType, // Automatic | Manual
}Program Escrow:
ProgramScheduleReleased {
program_id: String,
schedule_id: u64,
amount: i128,
recipient: Address,
released_at: u64,
released_by: Address,
release_type: ReleaseType, // Automatic | Manual
}// 4-year vesting schedule with quarterly releases
let quarterly_timestamp = start_time + (90 * 24 * 60 * 60);
let quarterly_amount = total_amount / 16;
for quarter in 0..16 {
contract.create_release_schedule(
&bounty_id,
&quarterly_amount,
&quarterly_timestamp + (quarter * 90 * 24 * 60 * 60),
&developer_address,
);
}// Immediate prize + milestone bonuses
contract.create_program_release_schedule(
&"Hackathon2024",
&1000_0000000, // Main prize
¤t_time, // Immediate
&winner_address,
);
contract.create_program_release_schedule(
&"Hackathon2024",
&200_0000000, // Documentation bonus
&(current_time + 7 * 24 * 60 * 60), // 1 week later
&winner_address,
);// Development milestones with different completion times
let milestones = vec![
(30 * 24 * 60 * 60, 500_0000000), // 30 days: MVP
(60 * 24 * 60 * 60, 300_0000000), // 60 days: Beta
(90 * 24 * 60 * 60, 200_0000000), // 90 days: Production
];
for (days_offset, amount) in milestones {
contract.create_release_schedule(
&bounty_id,
&amount,
&(start_time + days_offset),
&developer_address,
);
}- Authorization: Only admins can create bounty schedules; only authorized payout keys can create program schedules
- Balance Validation: Schedules cannot exceed available escrow/program funds
- Timestamp Validation: Release timestamps must be in the future
- Duplicate Prevention: Each schedule ID is unique per bounty/program
- Audit Trail: Complete history tracking for transparency
- Plan Ahead: Create all schedules upfront when funds are locked
- Use Clear Timestamps: Use Unix timestamps for consistency
- Monitor Events: Listen for schedule creation and release events
- Check Due Schedules: Regularly query for schedules ready for automatic release
- Validate Balances: Ensure sufficient funds before creating schedules
Common errors and their meanings:
ScheduleAlreadyReleased: Attempting to release an already released scheduleScheduleNotFound: Querying a non-existent scheduleInsufficientBalance: Creating schedules that exceed available fundsInvalidTimestamp: Using a past timestamp for releaseUnauthorized: Non-admin trying to create bounty schedules or non-authorized key for program schedules
- Event Monitoring: Set up event listeners for
schedule_createdandschedule_releasedevents - Automated Releases: Create bots to automatically trigger releases when timestamps pass
- Dashboard Integration: Use view functions to display pending and due schedules
- Batch Operations: Process multiple due schedules in batches for efficiency