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
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ testutils = ["soroban-sdk/testutils"]

[profile.release]
overflow-checks = true


42 changes: 42 additions & 0 deletions docs/offering-pagination-stability.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Offering Pagination Stability

## Overview

The Revora Revenue Share contract provides deterministic, stable pagination for all core entities to ensure that clients (e.g., front-ends, indexers) can reliably fetch large sets of data without hitting gas limits or skipping entries.

## Capability

### Core Paginated Getters

1. **Offerings**: `get_offerings_page(issuer, namespace, start, limit)`
* **Ordering**: Registration order (insertion order).
* **Stability**: Once an offering is registered, its position in the issuer's list is fixed.
2. **Issuers**: `get_issuers_page(start, limit)`
* **Ordering**: Global registration order.
* **Stability**: New issuers are appended to the global list.
3. **Namespaces**: `get_namespaces_page(issuer, start, limit)`
* **Ordering**: Registration order for the specific issuer.
4. **Periods**: `get_periods_page(issuer, namespace, token, start, limit)`
* **Ordering**: Deposit order.
5. **Blacklist**: `get_blacklist_page(issuer, namespace, token, start, limit)`
* **Ordering**: Insertion order.
6. **Whitelist**: `get_whitelist_page(issuer, namespace, token, start, limit)`
* **Ordering**: Lexicographical order by address (standard for Soroban Map keys).
7. **Pending Periods**: `get_pending_periods_page(issuer, namespace, token, holder, start, limit)`
* **Ordering**: Deposit order, starting from the holder's next unclaimed period.

### Stability & Security

* **Deterministic Ordering**: All paginated responses use stable storage structures (`Vec` or ordered `Map`) to ensure that the order is preserved across different blocks and calls.
* **Production-Grade Limits**: All `limit` parameters are capped by `MAX_PAGE_LIMIT` (default: 20) to prevent denial-of-service or transaction failure due to high compute/storage costs.
* **Cursor Behavior**: Functions return a `Option<u32>` as `next_cursor`. If `Some(cursor)` is returned, there are more entries. If `None`, the end of the list has been reached.

## Security Assumptions

* **Read-Only Safety**: Paginated getters are read-only and do not mutate state. They can be safely called via `simulateTransaction` without gas costs for the user.
* **Immutability**: Offerings, periods, and issuers are generally append-only. Whitelist/Blacklist can be modified, but their ordering mechanisms (Address keys for Whitelist, Order Vec for Blacklist) remain stable.

## Developer Notes

* Always use the returned `next_cursor` for the next call to avoid missing items if the list grows between calls.
* The `limit` parameter is a suggestion; the contract may return fewer items than requested if the end of the list is reached or if the limit exceeds the internal cap.
47 changes: 47 additions & 0 deletions docs/per-offering-emergency-pause.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Per-Offering Emergency Pause

## Overview
The Per-Offering Emergency Pause mechanism allows authorized roles (Admin, Safety, Issuer) to halt all state-mutating operations for a specific offering without affecting the rest of the contract. This granular control is essential for managing individual offering risks or responding to suspicious activities localized to a single issuance.

## Security Roles and Authorizations
The following roles are authorized to pause or unpause an offering:
- **Global Admin**: Full control to pause/unpause ANY offering.
- **Safety Role**: Dedicated emergency role (configured during initialization) authorized to pause/unpause any offering.
- **Current Issuer**: The current authorized issuer of the specific offering may pause it at any time.

## Protected Entrypoints
When an offering is paused, the following state-mutating functions will return `RevoraError::OfferingPaused` (code `31`):
- `do_deposit_revenue`
- `report_revenue`
- `blacklist_add` / `blacklist_remove`
- `whitelist_add` / `whitelist_remove`
- `set_concentration_limit` / `report_concentration`
- `set_rounding_mode`
- `set_investment_constraints`
- `set_min_revenue_threshold`
- `set_snapshot_config`
- `set_holder_share`
- `set_meta_delegate`
- `meta_set_holder_share`
- `meta__approve_revenue_report`
- `claim`
- `set_report_window` / `set_claim_window` / `set_claim_delay`
- `set_offering_metadata`

## Implicit Assumptions & Security Notes
1. **Flash-Loan Resistance**: Pause checks are performed at the beginning of each state-mutating call. Even within the same transaction, if an offering is paused, all subsequent mutating calls will fail.
2. **Read-Only Access**: View functions (e.g., `get_offering`, `get_holder_share`, `get_claimable`) remain operational during a pause to allow users to verify their state.
3. **Issuer Autonomy**: Allowing issuers to pause their own offerings ensures they can act faster than a global admin if they detect an issue with their specific offering's off-chain reporting.
4. **State Persistence**: The pause state is stored in persistent storage under `DataKey::PausedOffering(OfferingId)` and survives contract upgrades and Ledger ttl extensions.

## Storage Layout
```rust
pub enum DataKey {
// ... other keys ...
/// Per-offering pause flag; when true, state-mutating ops for that offering are disabled.
PausedOffering(OfferingId),
}
```

## Error Codes
- `RevoraError::OfferingPaused` (31): Returned when an operation is attempted on a paused offering.
21 changes: 21 additions & 0 deletions docs/token-vesting-core.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Token Vesting Core

## Overview
The Token Vesting Core capability is a production-grade standalone primitive for vesting token distributions to team members, advisors, and other stakeholders securely.

## Features
- **Multiple Schedules:** Admin can create multiple vesting schedules per beneficiary.
- **Vesting Mechanism:** Supports linear vesting over time and a hard cliff.
- **Cancellations:** Admin can cleanly cancel a schedule; only the unvested portion is forfeit.
- **Claim Processing:** Beneficiaries independently claim vested tokens.

## Architecture & Security Assumptions
1. **Admin Control**: Only an initialized admin address can create or cancel schedules.
2. **Deterministic Computation**: Vested amounts are computed mathematically on-the-fly (`start_time`, `end_time`, `cliff_time`) and use saturating arithmetic to prevent underflow/overflow.
3. **Immutability of the Past**: Canceling a schedule does not impact already claimed or vested amounts that have accrued up until the cancellation threshold.
4. **Zero-Trust Claims**: Beneficiaries securely claim what is theirs over the timeline without admin intervention being strictly required, up to the mathematically provable vested amount.

## Edge Cases Mitigated
- Zero duration handling and inverted cliff bounds handling.
- Claiming prior to a cliff returning absolute zero safely.
- Safe division and saturating multiplication to avoid panic traps under network stress.
40 changes: 40 additions & 0 deletions docs/vesting-schedule-amendment-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Vesting Schedule Amendment Flow

## Overview
The Vesting Schedule Amendment Flow allows the contract administrator to modify the parameters of an existing vesting schedule. This is a critical administrative feature for handling changes in team roles, performance-based adjustments, or error corrections in initial schedule setups.

## Key Features
- **Total Amount Adjustment**: Increase or decrease the total amount of tokens in the schedule.
- **Timeline Refactoring**: Update start time, cliff duration, and total duration.
- **Safety Guards**: Prevents reducing the total amount below what has already been claimed.
- **Status Validation**: Only active (non-cancelled) schedules can be amended.

## Security Assumptions and Rules
1. **Authorized Access**: Only the address initialized as `Admin` can call `amend_schedule`.
2. **Accounting Integrity**: The contract enforces `new_total_amount >= claimed_amount`. This ensures that even if a schedule is reduced, the tokens already claimed by the beneficiary remain accounted for and the schedule doesn't enter an invalid state.
3. **Parameter Validity**:
- `new_duration_secs > 0`: Prevents division-by-zero errors in vesting calculations.
- `new_cliff_duration_secs <= new_duration_secs`: Ensures the cliff occurs within the vesting period.
4. **Immutability of Cancelled Schedules**: Once a schedule is cancelled, it cannot be amended. This prevents "reviving" a forfeit schedule through parameter manipulation.

## Implementation Details
The `amend_schedule` function updates the `VestingSchedule` struct in persistent storage. After amendment, any subsequent calls to `get_claimable_vesting` or `claim_vesting` will use the updated parameters for linear calculation.

### Event Emission
Every successful amendment emits a `vest_amd` event containing:
- `admin`: The authorized caller.
- `beneficiary`: The recipient of the vesting.
- `schedule_index`: The specific schedule modified.
- `new_total_amount`, `new_start_time`, `new_cliff_time`, `new_end_time`.

## Example Flow
1. Admin creates a schedule for 1000 tokens over 1 year.
2. After 6 months, the beneficiary has claimed 500 tokens.
3. Admin decides to increase the total to 2000 tokens and extend the duration to 2 years.
4. Admin calls `amend_schedule` with the new parameters.
5. The beneficiary can now continue claiming based on the new 2000-token, 2-year linear curve, minus the 500 tokens already claimed.

## Technical Errors
- `AmendmentNotAllowed`: Thrown if attempting to amend a cancelled schedule.
- `InvalidAmount`: Thrown if `new_total_amount < claimed_amount`.
- `InvalidDuration` / `InvalidCliff`: Thrown if timing parameters are logically inconsistent.
Loading
Loading