@@ -652,3 +652,118 @@ fn test_bonus_pool_zero_behaves_identically() {
652652 assert_eq ! ( c. get_invoice( & id) . status, InvoiceStatus :: Released ) ;
653653 assert_eq ! ( tk. balance( & recipient) , 200 ) ;
654654}
655+
656+ #[ test]
657+ #[ should_panic( expected = "group members not fully funded" ) ]
658+ fn test_group_partial_fund_blocks_release ( ) {
659+ let ( env, contract_id, token_id) = setup ( ) ;
660+ let c = client ( & env, & contract_id) ;
661+
662+ let creator = Address :: generate ( & env) ;
663+ let payer = Address :: generate ( & env) ;
664+ let r1 = Address :: generate ( & env) ;
665+ let r2 = Address :: generate ( & env) ;
666+
667+ let stellar_asset = StellarAssetClient :: new ( & env, & token_id) ;
668+ stellar_asset. mint ( & payer, & 1_000 ) ;
669+
670+ env. ledger ( ) . set_timestamp ( 1_000 ) ;
671+
672+ let mut rec1 = Vec :: new ( & env) ;
673+ rec1. push_back ( r1. clone ( ) ) ;
674+ let mut amt1 = Vec :: new ( & env) ;
675+ amt1. push_back ( 100_i128 ) ;
676+
677+ let mut rec2 = Vec :: new ( & env) ;
678+ rec2. push_back ( r2. clone ( ) ) ;
679+ let mut amt2 = Vec :: new ( & env) ;
680+ amt2. push_back ( 200_i128 ) ;
681+
682+ let id1 = c. create_invoice ( & creator, & rec1, & amt1, & token_id, & 9_999_u64 ) ;
683+ let id2 = c. create_invoice ( & creator, & rec2, & amt2, & token_id, & 9_999_u64 ) ;
684+
685+ let mut ids = Vec :: new ( & env) ;
686+ ids. push_back ( id1) ;
687+ ids. push_back ( id2) ;
688+ c. create_invoice_group ( & ids) ;
689+
690+ // Fund only invoice 1 fully.
691+ c. pay ( & payer, & id1, & 100_i128 ) ;
692+
693+ // Attempt to release invoice 1 — should panic because invoice 2 is not funded.
694+ c. release ( & id1) ;
695+ }
696+
697+ #[ test]
698+ fn test_group_all_funded_releases_both ( ) {
699+ let ( env, contract_id, token_id) = setup ( ) ;
700+ let c = client ( & env, & contract_id) ;
701+ let tk = token_client ( & env, & token_id) ;
702+
703+ let creator = Address :: generate ( & env) ;
704+ let payer = Address :: generate ( & env) ;
705+ let r1 = Address :: generate ( & env) ;
706+ let r2 = Address :: generate ( & env) ;
707+
708+ let stellar_asset = StellarAssetClient :: new ( & env, & token_id) ;
709+ stellar_asset. mint ( & payer, & 1_000 ) ;
710+
711+ env. ledger ( ) . set_timestamp ( 1_000 ) ;
712+
713+ let mut rec1 = Vec :: new ( & env) ;
714+ rec1. push_back ( r1. clone ( ) ) ;
715+ let mut amt1 = Vec :: new ( & env) ;
716+ amt1. push_back ( 100_i128 ) ;
717+
718+ let mut rec2 = Vec :: new ( & env) ;
719+ rec2. push_back ( r2. clone ( ) ) ;
720+ let mut amt2 = Vec :: new ( & env) ;
721+ amt2. push_back ( 200_i128 ) ;
722+
723+ let id1 = c. create_invoice ( & creator, & rec1, & amt1, & token_id, & 9_999_u64 ) ;
724+ let id2 = c. create_invoice ( & creator, & rec2, & amt2, & token_id, & 9_999_u64 ) ;
725+
726+ let mut ids = Vec :: new ( & env) ;
727+ ids. push_back ( id1) ;
728+ ids. push_back ( id2) ;
729+ c. create_invoice_group ( & ids) ;
730+
731+ // Fund both invoices fully.
732+ c. pay ( & payer, & id1, & 100_i128 ) ;
733+ c. pay ( & payer, & id2, & 200_i128 ) ;
734+
735+ // Release via either member — both should be released.
736+ c. release ( & id1) ;
737+
738+ assert_eq ! ( c. get_invoice( & id1) . status, InvoiceStatus :: Released ) ;
739+ assert_eq ! ( c. get_invoice( & id2) . status, InvoiceStatus :: Released ) ;
740+ assert_eq ! ( tk. balance( & r1) , 100 ) ;
741+ assert_eq ! ( tk. balance( & r2) , 200 ) ;
742+ }
743+
744+ #[ test]
745+ fn test_non_grouped_invoice_unaffected ( ) {
746+ let ( env, contract_id, token_id) = setup ( ) ;
747+ let c = client ( & env, & contract_id) ;
748+ let tk = token_client ( & env, & token_id) ;
749+
750+ let creator = Address :: generate ( & env) ;
751+ let payer = Address :: generate ( & env) ;
752+ let recipient = Address :: generate ( & env) ;
753+
754+ let stellar_asset = StellarAssetClient :: new ( & env, & token_id) ;
755+ stellar_asset. mint ( & payer, & 300 ) ;
756+
757+ env. ledger ( ) . set_timestamp ( 1_000 ) ;
758+
759+ let mut recipients = Vec :: new ( & env) ;
760+ recipients. push_back ( recipient. clone ( ) ) ;
761+ let mut amounts = Vec :: new ( & env) ;
762+ amounts. push_back ( 300_i128 ) ;
763+
764+ let id = c. create_invoice ( & creator, & recipients, & amounts, & token_id, & 9_999_u64 ) ;
765+ c. pay ( & payer, & id, & 300_i128 ) ;
766+
767+ assert_eq ! ( c. get_invoice( & id) . status, InvoiceStatus :: Released ) ;
768+ assert_eq ! ( tk. balance( & recipient) , 300 ) ;
769+ }
0 commit comments