Filed from the second-wave repository audit (issue 21/100). See the audit summary for full category context.
- Location:
contracts/stream_contract/src/lib.rs:619-627
- Problem:
resume_stream only checks stream.paused, not is_active (unlike pause_stream, which calls validate_stream_active). cancel_stream sets is_active=false/status=Cancelled but never clears paused. A paused-then-cancelled stream can still be "resumed," setting status = Active while is_active stays false — a permanently corrupted, self-contradictory on-chain record.
- Evidence:
resume_stream body has no validate_stream_active/is_active check.
- Suggested implementation: Add an
is_active check (return StreamError::StreamNotActive if false) at the top of resume_stream, and/or have cancel_stream clear paused as part of cancellation.
- Acceptance criteria: A new contract test for the
pause → cancel → resume sequence asserts resume_stream returns an error and stream state is unchanged.
- Difficulty: S
- Expected impact: Eliminates a reachable on-chain state-corruption path with no recovery mechanism (contract state is immutable once corrupted).
contracts/stream_contract/src/lib.rs:619-627resume_streamonly checksstream.paused, notis_active(unlikepause_stream, which callsvalidate_stream_active).cancel_streamsetsis_active=false/status=Cancelledbut never clearspaused. A paused-then-cancelled stream can still be "resumed," settingstatus = Activewhileis_activestaysfalse— a permanently corrupted, self-contradictory on-chain record.resume_streambody has novalidate_stream_active/is_activecheck.is_activecheck (returnStreamError::StreamNotActiveif false) at the top ofresume_stream, and/or havecancel_streamclearpausedas part of cancellation.pause → cancel → resumesequence assertsresume_streamreturns an error and stream state is unchanged.