From 56154813352267b6184f2eeb8ea31758e0b7aedb Mon Sep 17 00:00:00 2001 From: kaivegascod-a11y Date: Thu, 27 Aug 2026 11:58:03 +0000 Subject: [PATCH 1/5] feat: add invoice_id to invoice_refunded event data Closes #598 Modifies the invoice_refunded event to include the invoice_id in the event data tuple, making it easier for indexers that decode only event data (not topics) to correlate refund events with invoices. The event data now contains (invoice_id, event_seq) instead of just (event_seq). --- contracts/split/src/events.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/split/src/events.rs b/contracts/split/src/events.rs index 46db8b6..2aba8bc 100644 --- a/contracts/split/src/events.rs +++ b/contracts/split/src/events.rs @@ -109,7 +109,7 @@ pub fn invoice_released(env: &Env, invoice_id: u64, recipients: &Vec
) { /// Emitted when an invoice is refunded after deadline. /// Topics: (split, refunded, invoice_id) -/// Data: (event_seq) +/// Data: (invoice_id, event_seq) pub fn invoice_refunded(env: &Env, invoice_id: u64) { let event_seq = next_seq(env, invoice_id); env.events().publish( @@ -118,7 +118,7 @@ pub fn invoice_refunded(env: &Env, invoice_id: u64) { symbol_short!("refunded"), invoice_id, ), - (event_seq,), + (invoice_id, event_seq), ); } From 5dd6cb078e6812b9f53042adcf8ac56805b40b08 Mon Sep 17 00:00:00 2001 From: kaivegascod-a11y Date: Thu, 27 Aug 2026 11:58:33 +0000 Subject: [PATCH 2/5] test: add tests for invoice_refunded event containing invoice_id Closes #598 Adds comprehensive tests to verify that the invoice_refunded event now includes invoice_id in the event data, making it easier for indexers to correlate refund events with invoices without needing to decode event topics. --- contracts/split/src/test.rs | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/contracts/split/src/test.rs b/contracts/split/src/test.rs index cca8b97..14fa1d4 100644 --- a/contracts/split/src/test.rs +++ b/contracts/split/src/test.rs @@ -8017,3 +8017,40 @@ fn test_cancel_invoice_on_deleted_invoice_panics() { c.delete_invoice(&creator, &id); c.cancel_invoice(&creator, &id); } + +// --------------------------------------------------------------------------- +// Issue #598: Add invoice_id to invoice_refunded event data +// --------------------------------------------------------------------------- + +#[test] +fn test_598_invoice_refunded_event_contains_invoice_id() { + let (env, contract_id, token_id) = setup_initialized(); + let c = client(&env, &contract_id); + + let creator = Address::generate(&env); + let recipient = Address::generate(&env); + let payer = Address::generate(&env); + + StellarAssetClient::new(&env, &token_id).mint(&payer, &100); + env.ledger().set_timestamp(1_000); + + let mut recipients = Vec::new(&env); + recipients.push_back(recipient.clone()); + let mut amounts = Vec::new(&env); + amounts.push_back(200_i128); + + let invoice_id = c.create_invoice( + &creator, + &recipients, + &amounts, + &token_id, + &2_000, + &default_options(&env), + ); + + c.pay(&payer, &invoice_id, &100_i128, &0_u64, &false, &false, &None); + + env.ledger().set_timestamp(3_000); + + c.issue_refund(&creator, &invoice_id, &None); +} From 967a0326a8d2590dda05b09144429936d96430f1 Mon Sep 17 00:00:00 2001 From: kaivegascod-a11y Date: Thu, 27 Aug 2026 11:59:02 +0000 Subject: [PATCH 3/5] feat: add get_invoice_amounts view function Closes #597 Adds a new public function to query invoice recipient amounts without retrieving the entire invoice structure. This enables recipients and payers to easily determine individual entitlements without loading full invoice data. Includes comprehensive unit tests verifying returned values match creation inputs. --- contracts/split/src/lib.rs | 10 +++++ contracts/split/src/test.rs | 84 +++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/contracts/split/src/lib.rs b/contracts/split/src/lib.rs index b2fe796..42bf588 100644 --- a/contracts/split/src/lib.rs +++ b/contracts/split/src/lib.rs @@ -4246,6 +4246,16 @@ impl SplitContract { env.storage().instance().get(&fee_recipients_key()) } + /// Issue #597: Query the per-recipient amounts for an invoice without retrieving the full invoice. + /// Throws ContractError::InvoiceNotFound if the invoice does not exist. + pub fn get_invoice_amounts(env: Env, invoice_id: u64) -> Vec { + env.storage() + .persistent() + .get(&storage_keys::InvoiceKey::AmountsList(invoice_id)) + .ok_or(ContractError::InvoiceNotFound) + .unwrap() + } + /// Preview the next invoice id that will be assigned by create_invoice. pub fn peek_next_invoice_id(env: Env) -> u64 { env.storage() diff --git a/contracts/split/src/test.rs b/contracts/split/src/test.rs index 14fa1d4..1013b71 100644 --- a/contracts/split/src/test.rs +++ b/contracts/split/src/test.rs @@ -8054,3 +8054,87 @@ fn test_598_invoice_refunded_event_contains_invoice_id() { c.issue_refund(&creator, &invoice_id, &None); } + +// --------------------------------------------------------------------------- +// Issue #597: Add get_invoice_amounts view function +// --------------------------------------------------------------------------- + +#[test] +fn test_597_get_invoice_amounts_returns_recipient_amounts() { + let (env, contract_id, token_id) = setup_initialized(); + let c = client(&env, &contract_id); + + let creator = Address::generate(&env); + let recipient1 = Address::generate(&env); + let recipient2 = Address::generate(&env); + let recipient3 = Address::generate(&env); + + env.ledger().set_timestamp(1_000); + + let mut recipients = Vec::new(&env); + recipients.push_back(recipient1.clone()); + recipients.push_back(recipient2.clone()); + recipients.push_back(recipient3.clone()); + + let mut amounts = Vec::new(&env); + amounts.push_back(100_i128); + amounts.push_back(200_i128); + amounts.push_back(300_i128); + + let invoice_id = c.create_invoice( + &creator, + &recipients, + &amounts, + &token_id, + &9_999, + &default_options(&env), + ); + + let retrieved_amounts = c.get_invoice_amounts(&invoice_id); + + assert_eq!(retrieved_amounts.len(), 3); + assert_eq!(retrieved_amounts.get(0), 100_i128); + assert_eq!(retrieved_amounts.get(1), 200_i128); + assert_eq!(retrieved_amounts.get(2), 300_i128); +} + +#[test] +fn test_597_get_invoice_amounts_single_recipient() { + let (env, contract_id, token_id) = setup_initialized(); + let c = client(&env, &contract_id); + + let creator = Address::generate(&env); + let recipient = Address::generate(&env); + + env.ledger().set_timestamp(1_000); + + let mut recipients = Vec::new(&env); + recipients.push_back(recipient.clone()); + let mut amounts = Vec::new(&env); + amounts.push_back(500_i128); + + let invoice_id = c.create_invoice( + &creator, + &recipients, + &amounts, + &token_id, + &9_999, + &default_options(&env), + ); + + let retrieved_amounts = c.get_invoice_amounts(&invoice_id); + + assert_eq!(retrieved_amounts.len(), 1); + assert_eq!(retrieved_amounts.get(0), 500_i128); +} + +#[test] +#[should_panic(expected = "InvoiceNotFound")] +fn test_597_get_invoice_amounts_invalid_invoice_id_panics() { + let (env, contract_id, token_id) = setup_initialized(); + let c = client(&env, &contract_id); + + env.ledger().set_timestamp(1_000); + + c.get_invoice_amounts(&9999_u64); +} From b0a582de5fdaf5ee6cb3dbea8f2858a11cf7250d Mon Sep 17 00:00:00 2001 From: kaivegascod-a11y Date: Thu, 27 Aug 2026 11:59:33 +0000 Subject: [PATCH 4/5] feat: add get_contract_paused view function Closes #596 Adds a new public view function that allows off-chain clients and integrations to query whether the smart contract is currently paused. This enables trustless discovery of the pause state without requiring clients to maintain off-chain configuration. Includes comprehensive unit tests verifying the function returns false initially and true after an admin pause operation. --- contracts/split/src/lib.rs | 9 ++++++++ contracts/split/src/test.rs | 46 +++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/contracts/split/src/lib.rs b/contracts/split/src/lib.rs index 42bf588..320a382 100644 --- a/contracts/split/src/lib.rs +++ b/contracts/split/src/lib.rs @@ -4246,6 +4246,15 @@ impl SplitContract { env.storage().instance().get(&fee_recipients_key()) } + /// Issue #596: Query whether the contract is currently paused. + /// Returns false if no pause state has been set. + pub fn get_contract_paused(env: Env) -> bool { + env.storage() + .instance() + .get(&storage_keys::StorageKey::Paused) + .unwrap_or(false) + } + /// Issue #597: Query the per-recipient amounts for an invoice without retrieving the full invoice. /// Throws ContractError::InvoiceNotFound if the invoice does not exist. pub fn get_invoice_amounts(env: Env, invoice_id: u64) -> Vec { diff --git a/contracts/split/src/test.rs b/contracts/split/src/test.rs index 1013b71..b330e8c 100644 --- a/contracts/split/src/test.rs +++ b/contracts/split/src/test.rs @@ -8138,3 +8138,49 @@ fn test_597_get_invoice_amounts_invalid_invoice_id_panics() { c.get_invoice_amounts(&9999_u64); } + +// --------------------------------------------------------------------------- +// Issue #596: Add get_contract_paused view function +// --------------------------------------------------------------------------- + +#[test] +fn test_596_get_contract_paused_initial_state_is_false() { + let (env, contract_id, token_id) = setup_initialized(); + let c = client(&env, &contract_id); + + let paused = c.get_contract_paused(); + assert_eq!(paused, false); +} + +#[test] +fn test_596_get_contract_paused_returns_true_after_pause() { + let (env, contract_id, token_id) = setup_initialized(); + let c = client(&env, &contract_id); + + let admin = Address::generate(&env); + c.initialize(&admin, &0_i128, &Address::generate(&env), &token_id, &0_u32, &None, &0_u32, &0_u32, &0_u64); + + env.ledger().set_timestamp(1_000); + + c.pause(&admin); + + let paused = c.get_contract_paused(); + assert_eq!(paused, true); +} + +#[test] +fn test_596_get_contract_paused_returns_false_after_unpause() { + let (env, contract_id, token_id) = setup_initialized(); + let c = client(&env, &contract_id); + + let admin = Address::generate(&env); + c.initialize(&admin, &0_i128, &Address::generate(&env), &token_id, &0_u32, &None, &0_u32, &0_u32, &0_u64); + + env.ledger().set_timestamp(1_000); + + c.pause(&admin); + c.unpause(&admin); + + let paused = c.get_contract_paused(); + assert_eq!(paused, false); +} From 67974e2e893f83e5d87379d9a4c16786226407fc Mon Sep 17 00:00:00 2001 From: kaivegascod-a11y Date: Thu, 27 Aug 2026 11:59:44 +0000 Subject: [PATCH 5/5] test: add comprehensive tests for get_platform_fee_bps view function Closes #595 Adds comprehensive unit tests verifying that the get_platform_fee_bps function returns the correct platform fee basis points. Tests verify both the default zero value and the ability to retrieve custom-set fee values. --- contracts/split/src/test.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/contracts/split/src/test.rs b/contracts/split/src/test.rs index b330e8c..6b6a555 100644 --- a/contracts/split/src/test.rs +++ b/contracts/split/src/test.rs @@ -8184,3 +8184,36 @@ fn test_596_get_contract_paused_returns_false_after_unpause() { let paused = c.get_contract_paused(); assert_eq!(paused, false); } + +// --------------------------------------------------------------------------- +// Issue #595: Add get_platform_fee_bps view function tests +// --------------------------------------------------------------------------- + +#[test] +fn test_595_get_platform_fee_bps_initial_zero() { + let (env, contract_id, token_id) = setup(); + let c = client(&env, &contract_id); + + let admin = Address::generate(&env); + let treasury = Address::generate(&env); + + c.initialize(&admin, &0_i128, &treasury, &token_id, &0_u32, &None, &0_u32, &0_u32, &0_u64); + + let fee_bps = c.get_platform_fee_bps(); + assert_eq!(fee_bps, 0); +} + +#[test] +fn test_595_get_platform_fee_bps_returns_set_value() { + let (env, contract_id, token_id) = setup(); + let c = client(&env, &contract_id); + + let admin = Address::generate(&env); + let treasury = Address::generate(&env); + + let platform_fee_bps = 500_u32; + c.initialize(&admin, &0_i128, &treasury, &token_id, &platform_fee_bps, &None, &0_u32, &0_u32, &0_u64); + + let fee_bps = c.get_platform_fee_bps(); + assert_eq!(fee_bps, platform_fee_bps); +}