Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 33 additions & 11 deletions contracts/stream_contract/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,38 @@ pub enum StreamError {
StreamNotPaused = 13,
/// `pause_stream` was called on a stream that is already paused.
StreamAlreadyPaused = 14,
/// Operation requires an active stream, but the stream is inactive (cancelled or completed).
StreamNotActive = 15,
/// An amount or timestamp calculation exceeded the range of its type.
/// The protocol circuit breaker is engaged; token-in operations are halted.
ProtocolPaused = 15,
/// A step-tranche schedule declared no steps.
EmptyVestingSchedule = 16,
/// A step-tranche schedule declares more than `MAX_VESTING_STEPS` steps.
TooManyVestingSteps = 17,
/// Step unlock times are not strictly monotonically increasing.
NonMonotonicVestingSteps = 18,
/// A step's `unlock_amount` is zero or negative.
InvalidVestingStepAmount = 19,
/// Step amounts do not sum to the stream's deposited amount.
VestingStepTotalMismatch = 20,
/// A vesting step unlocks at or before the stream's start time.
VestingStepBeforeStart = 21,
/// Cliff time is not strictly after the stream start, or the cliff amount
/// leaves no room for the linear tail.
InvalidCliffParameters = 22,
/// `batch_withdraw` received more than `MAX_BATCH_WITHDRAW` stream IDs.
BatchTooLarge = 23,
/// Caller is not the protocol admin and not the emergency guardian, and
/// only the admin may perform this action.
NotGuardian = 24,
/// `migrate` was asked to move to a version this contract cannot reach.
UnsupportedMigration = 25,
/// The on-chain state is already at a version newer than this contract.
StateVersionTooNew = 26,
/// `top_up_stream` was called on a step-tranche stream.
///
/// Returned instead of letting `overflow-checks` panic and abort the whole
/// transaction, so callers get a typed failure they can handle.
ArithmeticOverflow = 16,
/// Operation requires a fully settled stream, but unwithdrawn funds remain.
///
/// Returned by `close_stream` when the stream is still active, has a
/// non-terminal status, or still holds a claimable / undeposited balance.
StreamStillActive = 17,
/// A step schedule must sum to exactly the deposited amount, so extra
/// tokens have nowhere to go: appending them to the final step would lock
/// the top-up until the last milestone, and ignoring them would strand them
/// as unclaimable residue. Rejecting is the only option that never lies to
/// the recipient about when funds become available.
TopUpUnsupported = 27,
}
90 changes: 85 additions & 5 deletions contracts/stream_contract/src/events.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use soroban_sdk::{contracttype, Address};
use soroban_sdk::{contracttype, Address, BytesN};

// ─── Wire Format ─────────────────────────────────────────────────────────────
//
Expand Down Expand Up @@ -167,13 +167,93 @@ pub struct StreamCompletedEvent {
pub total_withdrawn: i128,
}

/// Emitted when a settled stream's storage entry is pruned via `close_stream`.
/// Emitted whenever the protocol circuit breaker changes state.
///
/// Topic: `("stream_closed", stream_id)`
/// Topic: `("protocol_pause_status",)`
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct StreamClosedEvent {
pub struct ProtocolPauseStatusEvent {
/// The address that flipped the breaker (admin or emergency guardian).
pub caller: Address,
/// `true` when the protocol is now paused.
pub paused: bool,
/// Ledger timestamp of the transition.
pub timestamp: u64,
}

/// Emitted when the emergency guardian role is set or cleared.
///
/// Topic: `("emergency_guardian_updated",)`
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EmergencyGuardianUpdatedEvent {
pub admin: Address,
/// The newly configured guardian, or `None` when the role was cleared.
pub guardian: Option<Address>,
}

/// Emitted when a step-tranche (milestone) stream is created.
///
/// Topic: `("step_vesting_stream_created", stream_id)`
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct StepVestingStreamCreatedEvent {
pub stream_id: u64,
pub closer: Address,
pub sender: Address,
pub recipient: Address,
pub token_address: Address,
/// Net deposited amount after protocol fee deduction.
pub deposited_amount: i128,
/// Number of unlock steps in the schedule.
pub step_count: u32,
/// Absolute timestamp of the final unlock step.
pub last_unlock_time: u64,
}

/// Emitted when a hybrid cliff + linear stream is created.
///
/// Topic: `("hybrid_cliff_stream_created", stream_id)`
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HybridCliffStreamCreatedEvent {
pub stream_id: u64,
pub sender: Address,
pub recipient: Address,
pub token_address: Address,
/// Net deposited amount after protocol fee deduction.
pub deposited_amount: i128,
/// Absolute timestamp of the cliff unlock.
pub cliff_time: u64,
/// Amount released at `cliff_time`.
pub cliff_unlock_amount: i128,
/// Linear drip rate applied to the post-cliff remainder.
pub rate_per_second: i128,
}

/// Emitted when the contract's executable is replaced in place.
///
/// Topic: `("contract_upgraded",)`
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ContractUpgradedEvent {
pub admin: Address,
/// Executable hash in force before this call.
pub old_wasm_hash: BytesN<32>,
/// Executable hash installed by this call.
pub new_wasm_hash: BytesN<32>,
/// Ledger timestamp of the upgrade.
pub timestamp: u64,
}

/// Emitted when the on-chain state schema is migrated to a new version.
///
/// Topic: `("state_migrated",)`
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct StateMigratedEvent {
pub admin: Address,
/// Schema version before the migration. `0` means unversioned (pre-v1).
pub old_version: u32,
/// Schema version after the migration.
pub new_version: u32,
}
Loading
Loading