@@ -3,7 +3,40 @@ use lending_pool::{LendingPool, LendingPoolClient};
33use remittance_nft:: { RemittanceNFT , RemittanceNFTClient } ;
44use soroban_sdk:: testutils:: Ledger as _;
55use soroban_sdk:: token:: { Client as TokenClient , StellarAssetClient } ;
6- use soroban_sdk:: { testutils:: Address as _, Address , BytesN , Env , String } ;
6+ use soroban_sdk:: {
7+ contract, contractimpl, testutils:: Address as _, Address , BytesN , Env , String , Symbol ,
8+ } ;
9+
10+ #[ contract]
11+ pub struct MaliciousToken ;
12+
13+ #[ contractimpl]
14+ impl MaliciousToken {
15+ pub fn set_attack_target ( env : Env , manager : Address , loan_id : u32 ) {
16+ env. storage ( )
17+ . persistent ( )
18+ . set ( & Symbol :: new ( & env, "manager" ) , & manager) ;
19+ env. storage ( )
20+ . persistent ( )
21+ . set ( & Symbol :: new ( & env, "loan_id" ) , & loan_id) ;
22+ }
23+
24+ pub fn transfer ( env : Env , _from : Address , _to : Address , _amount : i128 ) {
25+ let manager: Address = env
26+ . storage ( )
27+ . persistent ( )
28+ . get ( & Symbol :: new ( & env, "manager" ) )
29+ . unwrap ( ) ;
30+ let loan_id: u32 = env
31+ . storage ( )
32+ . persistent ( )
33+ . get ( & Symbol :: new ( & env, "loan_id" ) )
34+ . unwrap ( ) ;
35+ env. as_contract ( & manager, || {
36+ env. storage ( ) . persistent ( ) . remove ( & DataKey :: Loan ( loan_id) ) ;
37+ } ) ;
38+ }
39+ }
740
841fn setup_test < ' a > (
942 env : & Env ,
@@ -1335,6 +1368,42 @@ fn test_deposit_collateral_and_auto_release_on_full_repayment() {
13351368 ) ;
13361369}
13371370
1371+ #[ test]
1372+ fn test_deposit_collateral_rejects_loan_removed_during_token_transfer ( ) {
1373+ let env = Env :: default ( ) ;
1374+ env. mock_all_auths_allowing_non_root_auth ( ) ;
1375+
1376+ let ( manager, nft_client, pool_client, token_id, _token_admin) = setup_test ( & env) ;
1377+ let borrower = Address :: generate ( & env) ;
1378+
1379+ let history_hash = BytesN :: from_array ( & env, & [ 0u8 ; 32 ] ) ;
1380+ nft_client. mint (
1381+ & borrower,
1382+ & 650 ,
1383+ & history_hash,
1384+ & String :: from_str ( & env, "ipfs://QmTest" ) ,
1385+ & None ,
1386+ ) ;
1387+
1388+ let stellar_token = StellarAssetClient :: new ( & env, & token_id) ;
1389+ stellar_token. mint ( & pool_client, & 20_000 ) ;
1390+ stellar_token. mint ( & borrower, & 20_000 ) ;
1391+
1392+ let loan_id = manager. request_loan ( & borrower, & 1_000 , & 17280 ) ;
1393+ manager. approve_loan ( & loan_id) ;
1394+
1395+ let malicious = env. register ( MaliciousToken , ( ) ) ;
1396+ let malicious_client = MaliciousTokenClient :: new ( & env, & malicious) ;
1397+ malicious_client. set_attack_target ( & manager. address , & loan_id) ;
1398+
1399+ env. as_contract ( & manager. address , || {
1400+ env. storage ( ) . instance ( ) . set ( & DataKey :: Token , & malicious) ;
1401+ } ) ;
1402+
1403+ let result = manager. try_deposit_collateral ( & loan_id, & 300 ) ;
1404+ assert_eq ! ( result, Err ( Ok ( LoanError :: LoanNotFound ) ) ) ;
1405+ }
1406+
13381407#[ test]
13391408fn test_collateral_is_seized_on_default ( ) {
13401409 let env = Env :: default ( ) ;
0 commit comments