@@ -3,7 +3,7 @@ use soroban_sdk::{
33 testutils:: { Address as _, Events , MockAuth , MockAuthInvoke } ,
44 token:: { StellarAssetClient , TokenClient } ,
55 xdr:: SorobanAuthorizationEntry ,
6- Address , Env , IntoVal , Symbol , TryIntoVal ,
6+ Address , Env , Error as SorobanError , IntoVal , Symbol , TryIntoVal ,
77} ;
88
99fn create_token_contract < ' a > (
@@ -321,3 +321,115 @@ fn test_deposit_emits_event() {
321321 assert_eq ! ( amount, 500 ) ;
322322 assert_eq ! ( token, token_address) ;
323323}
324+
325+ /// Asserts exact auth requirements using only `mock_auths` (no `mock_all_auths`):
326+ /// - `initialize` requires admin auth
327+ /// - `deposit` requires from (user) auth
328+ /// - `withdraw` requires admin auth
329+ /// - unauthorized `withdraw` (no auth) fails
330+ #[ test]
331+ fn test_mock_auths_granular_auth_requirements ( ) {
332+ let env = Env :: default ( ) ;
333+
334+ let admin = Address :: generate ( & env) ;
335+ let user = Address :: generate ( & env) ;
336+ let unauthorized = Address :: generate ( & env) ;
337+
338+ let ( token_address, token_client, admin_client) = create_token_contract ( & env, & admin) ;
339+ let treasury_id = env. register_contract ( None , Treasury ) ;
340+ let treasury_client = TreasuryClient :: new ( & env, & treasury_id) ;
341+
342+ // --- token mint: admin auth ---
343+ env. mock_auths ( & [ MockAuth {
344+ address : & admin,
345+ invoke : & MockAuthInvoke {
346+ contract : & token_address,
347+ fn_name : "mint" ,
348+ args : soroban_sdk:: vec![ & env, user. clone( ) . into_val( & env) , 1000_i128 . into_val( & env) ] ,
349+ sub_invokes : & [ ] ,
350+ } ,
351+ } ] ) ;
352+ admin_client. mint ( & user, & 1000 ) ;
353+
354+ // --- initialize: requires admin auth ---
355+ env. mock_auths ( & [ MockAuth {
356+ address : & admin,
357+ invoke : & MockAuthInvoke {
358+ contract : & treasury_id,
359+ fn_name : "initialize" ,
360+ args : soroban_sdk:: vec![
361+ & env,
362+ admin. clone( ) . into_val( & env) ,
363+ token_address. clone( ) . into_val( & env) ,
364+ ] ,
365+ sub_invokes : & [ ] ,
366+ } ,
367+ } ] ) ;
368+ treasury_client. initialize ( & admin, & token_address) ;
369+
370+ // --- deposit: requires from (user) auth; sub-invokes token transfer ---
371+ let deposit_amount = 600_i128 ;
372+ env. mock_auths ( & [ MockAuth {
373+ address : & user,
374+ invoke : & MockAuthInvoke {
375+ contract : & treasury_id,
376+ fn_name : "deposit" ,
377+ args : soroban_sdk:: vec![
378+ & env,
379+ user. clone( ) . into_val( & env) ,
380+ deposit_amount. into_val( & env) ,
381+ ] ,
382+ sub_invokes : & [ MockAuthInvoke {
383+ contract : & token_address,
384+ fn_name : "transfer" ,
385+ args : soroban_sdk:: vec![
386+ & env,
387+ user. clone( ) . into_val( & env) ,
388+ treasury_id. clone( ) . into_val( & env) ,
389+ deposit_amount. into_val( & env) ,
390+ ] ,
391+ sub_invokes : & [ ] ,
392+ } ] ,
393+ } ,
394+ } ] ) ;
395+ treasury_client. deposit ( & user, & deposit_amount) ;
396+
397+ assert_eq ! ( token_client. balance( & treasury_id) , 600 ) ;
398+ assert_eq ! ( token_client. balance( & user) , 400 ) ;
399+
400+ // --- withdraw: requires admin auth ---
401+ let withdraw_amount = 100_i128 ;
402+ env. mock_auths ( & [ MockAuth {
403+ address : & admin,
404+ invoke : & MockAuthInvoke {
405+ contract : & treasury_id,
406+ fn_name : "withdraw" ,
407+ args : soroban_sdk:: vec![
408+ & env,
409+ user. clone( ) . into_val( & env) ,
410+ withdraw_amount. into_val( & env) ,
411+ ] ,
412+ sub_invokes : & [ MockAuthInvoke {
413+ contract : & token_address,
414+ fn_name : "transfer" ,
415+ args : soroban_sdk:: vec![
416+ & env,
417+ treasury_id. clone( ) . into_val( & env) ,
418+ user. clone( ) . into_val( & env) ,
419+ withdraw_amount. into_val( & env) ,
420+ ] ,
421+ sub_invokes : & [ ] ,
422+ } ] ,
423+ } ,
424+ } ] ) ;
425+ treasury_client. withdraw ( & user, & withdraw_amount) ;
426+
427+ assert_eq ! ( token_client. balance( & treasury_id) , 500 ) ;
428+ assert_eq ! ( token_client. balance( & user) , 500 ) ;
429+
430+ // --- unauthorized withdraw: no auth set → must fail ---
431+ let empty: & [ soroban_sdk:: xdr:: SorobanAuthorizationEntry ] = & [ ] ;
432+ env. set_auths ( empty) ;
433+ let result = treasury_client. try_withdraw ( & unauthorized, & 50 ) ;
434+ assert ! ( result. is_err( ) , "unauthorized withdraw must fail" ) ;
435+ }
0 commit comments