Skip to content

[Contracts] withdraw/cancel transfer tokens before persisting stream state (CEI violation / reentrancy surface) #789

Description

@grantfox-oss

Telegram (ask questions / claim the issue here first): https://t.me/+DOylgFv1jyJlNzM0

Why this matters

transfer_and_update_stream (lib.rs:396-407) calls token_client.transfer to the recipient and mutates only a local Stream; withdraw persists it afterward at lib.rs:448. cancel_stream transfers to recipient (lib.rs:502) and sender (lib.rs:512) before save_stream (lib.rs:523). token_address is an arbitrary caller-supplied contract (validate_token_contract only checks a decimals() symbol exists, lib.rs:314), so a token with a transfer hook could re-enter while storage still shows the pre-update is_active/withdrawn_amount, enabling a double payout.

Acceptance criteria

  • Persist stream state (save_stream) before any token_client.transfer in withdraw and cancel_stream, or add an explicit reentrancy guard
  • Add a regression test with a token stub that re-enters withdraw, asserting no double payout
  • If reordering is infeasible, document that only trusted/audited tokens may be streamed

Files to touch

  • contracts/stream_contract/src/lib.rs

Out of scope

  • Replacing the Soroban token interface

Metadata

Metadata

Assignees

Labels

Stellar WaveIssues in the Stellar wave programcontractsSmart contract related tasksrustPull requests that update rust codesecuritySecurity related tasks

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions