Join the discussion on Telegram
Why this matters
The contract intentionally allows rate_per_second == 0 (when amount < duration, integer division rounds the rate to 0 — see test_create_stream_zero_rate in contracts/stream_contract/src/test.rs). The result is a "stream" that locks the sender's tokens in the contract but never accrues anything to the recipient and can only be recovered via cancel_stream. This is almost always a user mistake (wrong decimals / too-long duration), and it is the root cause of the backend indexer division-by-zero bug. Rejecting it at creation protects users from accidentally bricking funds and removes the foot-gun.
Acceptance criteria
Files to touch
contracts/stream_contract/src/lib.rs
contracts/stream_contract/src/errors.rs
contracts/stream_contract/src/test.rs
Out of scope
- The backend indexer guard (tracked separately and should remain defensive regardless).
Join the discussion on Telegram
Why this matters
The contract intentionally allows
rate_per_second == 0(whenamount < duration, integer division rounds the rate to 0 — seetest_create_stream_zero_rateincontracts/stream_contract/src/test.rs). The result is a "stream" that locks the sender's tokens in the contract but never accrues anything to the recipient and can only be recovered viacancel_stream. This is almost always a user mistake (wrong decimals / too-long duration), and it is the root cause of the backend indexer division-by-zero bug. Rejecting it at creation protects users from accidentally bricking funds and removes the foot-gun.Acceptance criteria
create_stream(contracts/stream_contract/src/lib.rs), after computingrate_per_second, return a newStreamError::InvalidRate(add tocontracts/stream_contract/src/errors.rs) when the rate would be0.top_up_streamif a top-up could leave the effective rate at 0 (evaluate whether needed).test_create_stream_zero_rateto assert the call is now rejected, and add a boundary test whereamount == duration(rate exactly 1) still succeeds.Files to touch
contracts/stream_contract/src/lib.rscontracts/stream_contract/src/errors.rscontracts/stream_contract/src/test.rsOut of scope