Skip to content

feat(stream-contract): protocol pause, milestone vesting, upgrades, b… - #1460

Merged
blurbeast merged 2 commits into
LabsCrypt:mainfrom
Darkvader-ship-it:feat/protocol-pause-milestone-vesting-upgrade-batch
Sep 26, 2026
Merged

blurbeast merged 2 commits into
LabsCrypt:mainfrom
Darkvader-ship-it:feat/protocol-pause-milestone-vesting-upgrade-batch

Conversation

@Darkvader-ship-it

Copy link
Copy Markdown
Contributor

Verified: cargo fmt, clippy -D warnings, release wasm build, 216 tests passing, 97.5% line coverage.

Description

Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionalit…atch withdraw

Adds four protocol features to stream_contract, each with test coverage.

Protocol circuit breaker: ProtocolConfig gains is_protocol_paused and an optional emergency_guardian. set_protocol_pause takes the caller explicitly so authorization is unambiguous: admin or guardian may trip the breaker, only the admin may clear it. Creation and top-up entrypoints are gated, while withdraw, batch_withdraw and cancel_stream stay open so a pause can never trap or censor funds that have already vested.

Milestone vesting: VestingStep/VestingSchedule with a StepTranches variant (max 12 strictly increasing milestones that must sum to the post-fee net deposit) and a HybridCliffLinear variant. Claim and projected-end-time maths became schedule-aware. Step schedules reject top-ups, since extra deposit would have nowhere legitimate to go.

In-place upgrades: upgrade swaps the executable while preserving the address, and migrate moves state to schema v2. Streams are migrated lazily rather than in bulk because Soroban cannot enumerate persistent storage, so both loaders decode the legacy shape on read and rewrite on next write. Record shape is chosen by field count: a contracttype decode that overruns a shorter map raises a host error that aborts the invocation, so "try current, fall back to legacy" is not a recoverable path.

Batch withdrawals: batch_withdraw pays up to 30 streams in one call, working during a protocol pause and across mixed tokens and schedules. Per-stream ownership is enforced and each stream is committed to storage before its own transfer (CEI).y)

  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📚 Documentation update
  • 🔧 Refactoring (no functional changes)
  • ⚡ Performance improvement
  • 🧪 Test addition or update

Related Issues

Closes #

Changes Made

Testing

Test Coverage

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed

Test Steps

Breaking Changes

Breaking Changes:

Migration Guide:

Screenshots/Demo

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • Updated Postman/Hoppscotch API collections if routes changed
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published
  • I have checked for breaking changes and documented them if applicable

Additional Notes

…atch withdraw

Adds four protocol features to stream_contract, each with test coverage.

Protocol circuit breaker: ProtocolConfig gains is_protocol_paused and an
optional emergency_guardian. set_protocol_pause takes the caller explicitly
so authorization is unambiguous: admin or guardian may trip the breaker,
only the admin may clear it. Creation and top-up entrypoints are gated,
while withdraw, batch_withdraw and cancel_stream stay open so a pause can
never trap or censor funds that have already vested.

Milestone vesting: VestingStep/VestingSchedule with a StepTranches variant
(max 12 strictly increasing milestones that must sum to the post-fee net
deposit) and a HybridCliffLinear variant. Claim and projected-end-time
maths became schedule-aware. Step schedules reject top-ups, since extra
deposit would have nowhere legitimate to go.

In-place upgrades: upgrade swaps the executable while preserving the
address, and migrate moves state to schema v2. Streams are migrated lazily
rather than in bulk because Soroban cannot enumerate persistent storage, so
both loaders decode the legacy shape on read and rewrite on next write.
Record shape is chosen by field count: a contracttype decode that overruns
a shorter map raises a host error that aborts the invocation, so
"try current, fall back to legacy" is not a recoverable path.

Batch withdrawals: batch_withdraw pays up to 30 streams in one call,
working during a protocol pause and across mixed tokens and schedules.
Per-stream ownership is enforced and each stream is committed to storage
before its own transfer (CEI).

Verified: cargo fmt, clippy -D warnings, release wasm build, 216 tests
passing, 97.5% line coverage.
@blurbeast
blurbeast merged commit 15b7f0a into LabsCrypt:main Sep 26, 2026
3 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment