-
Notifications
You must be signed in to change notification settings - Fork 15
Feature/revenue service fee #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
2feeb02
f354df0
525336b
46111cc
e3f359f
ea0d838
069e99f
0df5476
83b2344
a5e180e
ac5e76f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,6 +41,23 @@ pub fn unpause(env: &Env) -> Result<(), VaultError> { | |
| Ok(()) | ||
| } | ||
|
|
||
| pub fn set_fee(env: &Env, new_fee_bps: u32) -> Result<(), VaultError> { | ||
| let admin = storage::get_admin(env).ok_or(VaultError::NotInitialized)?; | ||
| admin.require_auth(); | ||
| if new_fee_bps > 2000 { | ||
| return Err(VaultError::FeeTooHigh); | ||
| } | ||
| storage::set_fee_bps(env, new_fee_bps); | ||
| Ok(()) | ||
| } | ||
|
|
||
| pub fn set_treasury(env: &Env, treasury: &Address) -> Result<(), VaultError> { | ||
| let admin = storage::get_admin(env).ok_or(VaultError::NotInitialized)?; | ||
| admin.require_auth(); | ||
| storage::set_treasury(env, treasury); | ||
| Ok(()) | ||
| } | ||
|
|
||
| pub fn set_my_rate(env: &Env, expert: &Address, rate_per_second: i128) -> Result<(), VaultError> { | ||
| expert.require_auth(); | ||
|
|
||
|
|
@@ -221,32 +238,34 @@ pub fn finalize_session( | |
| return Err(VaultError::BookingNotPending); | ||
| } | ||
|
|
||
| // 4. Calculate payments. | ||
| // rate_per_second is stored in atomic units of the payment token, so this | ||
| // multiplication is safe for any token precision as long as the product fits i128. | ||
| let expert_pay = booking | ||
| .rate_per_second | ||
| .checked_mul(actual_duration as i128) | ||
| .ok_or(VaultError::Overflow)?; | ||
| let refund = booking.total_deposit - expert_pay; | ||
| // 4. Calculate payments | ||
| let gross_expert_pay = booking.rate_per_second * (actual_duration as i128); | ||
| let refund = booking.total_deposit - gross_expert_pay; | ||
|
|
||
| // Ensure calculations are valid | ||
| if expert_pay < 0 || refund < 0 { | ||
| if gross_expert_pay < 0 || refund < 0 { | ||
| return Err(VaultError::InvalidAmount); | ||
| } | ||
|
|
||
| let fee_bps = storage::get_fee_bps(env); | ||
| let fee_amount = (gross_expert_pay * fee_bps as i128) / 10_000; | ||
| let expert_net_pay = gross_expert_pay - fee_amount; | ||
|
|
||
| // 5. Get token contract | ||
| let token_address = storage::get_token(env); | ||
| let token_client = token::Client::new(env, &token_address); | ||
| let contract_address = env.current_contract_address(); | ||
|
|
||
| // 6. Execute transfers | ||
| // Pay expert | ||
| if expert_pay > 0 { | ||
| token_client.transfer(&contract_address, &booking.expert, &expert_pay); | ||
| if fee_amount > 0 { | ||
| if let Some(treasury) = storage::get_treasury(env) { | ||
| token_client.transfer(&contract_address, &treasury, &fee_amount); | ||
| } | ||
| } | ||
|
Comment on lines
+259
to
+263
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potential issue: Fee amount may be silently retained in contract when treasury is not set. When Consider one of these approaches:
🔧 Option 1: Skip fee if no treasury (recommended) let fee_bps = storage::get_fee_bps(env);
- let fee_amount = (gross_expert_pay * fee_bps as i128) / 10_000;
- let expert_net_pay = gross_expert_pay - fee_amount;
+ let treasury_opt = storage::get_treasury(env);
+ let fee_amount = if treasury_opt.is_some() {
+ (gross_expert_pay * fee_bps as i128) / 10_000
+ } else {
+ 0
+ };
+ let expert_net_pay = gross_expert_pay - fee_amount;
// ...
if fee_amount > 0 {
- if let Some(treasury) = storage::get_treasury(env) {
+ if let Some(treasury) = treasury_opt {
token_client.transfer(&contract_address, &treasury, &fee_amount);
}
}🔧 Option 2: Require treasury when fee is setIn pub fn set_fee(env: &Env, new_fee_bps: u32) -> Result<(), VaultError> {
let admin = storage::get_admin(env).ok_or(VaultError::NotInitialized)?;
admin.require_auth();
if new_fee_bps > 2000 {
return Err(VaultError::FeeTooHigh);
}
+ if new_fee_bps > 0 && storage::get_treasury(env).is_none() {
+ return Err(VaultError::TreasuryNotSet); // New error variant needed
+ }
storage::set_fee_bps(env, new_fee_bps);
Ok(())
}🤖 Prompt for AI Agents |
||
|
|
||
| if expert_net_pay > 0 { | ||
| token_client.transfer(&contract_address, &booking.expert, &expert_net_pay); | ||
| } | ||
|
|
||
| // Refund user | ||
| if refund > 0 { | ||
| token_client.transfer(&contract_address, &booking.user, &refund); | ||
| } | ||
|
|
@@ -255,7 +274,7 @@ pub fn finalize_session( | |
| storage::update_booking_status(env, booking_id, BookingStatus::Complete); | ||
|
|
||
| // 8. Emit SessionFinalized event | ||
| events::session_finalized(env, booking_id, actual_duration, expert_pay); | ||
| events::session_finalized(env, booking_id, actual_duration, expert_net_pay, fee_amount); | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: LightForgeHub/SkillSphere-Contracts
Length of output: 1187
Use checked arithmetic for graceful error handling in
finalize_session.Lines 242–250 use raw
i128arithmetic. While the workspace enablesoverflow-checks = truein all Cargo profiles (which causes panics on overflow rather than silent wrapping), it's better to handle potential overflows explicitly and returnVaultError::Overflowinstead of crashing. This improves user experience and gives the contract control over error handling.Proposed fix
🤖 Prompt for AI Agents