Skip to content

Commit af1a756

Browse files
committed
feat(contracts): settle recipient on cancel_stream
1 parent 61d1f86 commit af1a756

2 files changed

Lines changed: 24 additions & 12 deletions

File tree

contracts/stream_contract/src/lib.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -329,15 +329,21 @@ impl StreamContract {
329329
let now = env.ledger().timestamp();
330330
let accrued_amount = Self::calculate_claimable(&stream, now);
331331

332-
// Refund only the unspent balance minus accrued tokens (accrued tokens stay for recipient)
332+
let token_client = token::Client::new(&env, &stream.token_address);
333+
let contract_address = env.current_contract_address();
334+
335+
// Settle recipient immediately with all final claimable amount at cancellation.
336+
if accrued_amount > 0 {
337+
token_client.transfer(&contract_address, &stream.recipient, &accrued_amount);
338+
stream.withdrawn_amount = stream.withdrawn_amount.saturating_add(accrued_amount);
339+
}
340+
341+
// Refund remaining unspent balance after recipient settlement.
333342
let refunded_amount = stream
334343
.deposited_amount
335-
.saturating_sub(stream.withdrawn_amount)
336-
.saturating_sub(accrued_amount);
344+
.saturating_sub(stream.withdrawn_amount);
337345

338346
if refunded_amount > 0 {
339-
let token_client = token::Client::new(&env, &stream.token_address);
340-
let contract_address = env.current_contract_address();
341347
token_client.transfer(&contract_address, &sender, &refunded_amount);
342348
}
343349

contracts/stream_contract/src/test.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -872,20 +872,23 @@ fn test_cancel_stream_refunds_sender() {
872872
l.timestamp += 300;
873873
});
874874

875-
// Cancel stream: should refund 700 tokens to sender (1000 - 300 accrued)
875+
// Cancel stream: should pay 300 to recipient and refund 700 to sender
876876
client.cancel_stream(&sender, &stream_id);
877877

878878
let sender_balance_after = token_client.balance(&sender);
879879
let contract_balance_after = token_client.balance(&contract_id);
880+
let recipient_balance_after = token_client.balance(&recipient);
880881

881882
// Sender should receive 700 tokens back
882883
assert_eq!(sender_balance_after - sender_balance_before, 700);
883-
// Contract should have 300 tokens remaining (for recipient to withdraw)
884-
assert_eq!(contract_balance_after, 300);
884+
// Recipient should receive final claimable 300 immediately
885+
assert_eq!(recipient_balance_after, 300);
886+
// Contract should be fully drained
887+
assert_eq!(contract_balance_after, 0);
885888

886889
let stream = client.get_stream(&stream_id).unwrap();
887890
assert!(!stream.is_active);
888-
assert_eq!(stream.withdrawn_amount, 0); // Recipient hasn't withdrawn yet
891+
assert_eq!(stream.withdrawn_amount, 300);
889892
}
890893

891894
#[test]
@@ -921,14 +924,17 @@ fn test_cancel_stream_after_partial_withdrawal() {
921924
l.timestamp += 100;
922925
});
923926

924-
// Cancel stream: should refund 700 tokens to sender (1000 - 200 withdrawn - 100 accrued)
927+
// Cancel stream: should pay final 100 to recipient and refund 700 to sender
925928
client.cancel_stream(&sender, &stream_id);
926929

927930
let sender_balance_after = token_client.balance(&sender);
928931
let contract_balance_after = token_client.balance(&contract_id);
932+
let recipient_balance_after = token_client.balance(&recipient);
929933

930934
// Sender should receive 700 tokens back
931935
assert_eq!(sender_balance_after - sender_balance_before, 700);
932-
// Contract should have 100 tokens remaining (for recipient to withdraw)
933-
assert_eq!(contract_balance_after, 100);
936+
// Recipient should now hold total 300 (200 withdrawn earlier + 100 settled at cancel)
937+
assert_eq!(recipient_balance_after, 300);
938+
// Contract should be fully drained
939+
assert_eq!(contract_balance_after, 0);
934940
}

0 commit comments

Comments
 (0)