Skip to content
Open
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
466 changes: 466 additions & 0 deletions lib-blockchain/src/contracts/dev_grants/core.rs

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions lib-blockchain/src/contracts/dev_grants/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod core;
pub mod types;

pub use core::DevelopmentGrants;
pub use types::{ProposalId, Amount, Recipient, Disbursement, ProposalStatus, ProposalData};
104 changes: 104 additions & 0 deletions lib-blockchain/src/contracts/dev_grants/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use serde::{Deserialize, Serialize};

/// Unique identifier for a governance proposal
/// Invariant: ProposalId must be globally unique and non-repeating
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ProposalId(pub u64);

/// Amount in smallest unit (e.g., cents, satoshis)
/// Invariant: All amounts are non-negative and checked for overflow
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Amount(pub u128);

impl Amount {
/// Create a new Amount, panicking if zero
pub fn new(value: u128) -> Self {
assert!(value > 0, "Amount must be greater than zero");
Amount(value)
}

/// Create Amount from u128, allowing zero
pub fn from_u128(value: u128) -> Self {
Amount(value)
}

/// Check if amount is zero
pub fn is_zero(&self) -> bool {
self.0 == 0
}

/// Safe addition with overflow check
pub fn checked_add(&self, other: Amount) -> Option<Amount> {
self.0.checked_add(other.0).map(Amount)
}

/// Safe subtraction with underflow check
pub fn checked_sub(&self, other: Amount) -> Option<Amount> {
self.0.checked_sub(other.0).map(Amount)
}
}

/// Recipient of a grant (opaque identifier)
/// Invariant: No validation of recipient format or eligibility
/// That is governance's responsibility, not this contract's
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Recipient(pub Vec<u8>);

impl Recipient {
pub fn new(bytes: Vec<u8>) -> Self {
Recipient(bytes)
}
}

/// Immutable record of a governance-approved disbursement
/// Invariant A3 — Append-only ledger
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Disbursement {
/// Reference to the governance proposal that authorized this
/// Invariant G2 — Every disbursement must reference an approved proposal
pub proposal_id: ProposalId,

/// Who receives the grant
/// Invariant S2 — Recipient is opaque; no validation here
pub recipient: Recipient,

/// Amount transferred
pub amount: Amount,

/// Block height at execution
/// Used for audit trail only, not for logic
pub executed_at_height: u64,

/// Index of this disbursement in the append-only log
pub index: u64,
}

impl Disbursement {
pub fn new(proposal_id: ProposalId, recipient: Recipient, amount: Amount, height: u64, index: u64) -> Self {
Disbursement {
proposal_id,
recipient,
amount,
executed_at_height: height,
index,
}
}
}

/// Proposal status (governance authority owns this)
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ProposalStatus {
/// Proposal was approved by governance
Approved,
/// Proposal was rejected
Rejected,
/// Proposal execution was already completed
Executed,
}

/// State of a grant proposal (governance provides this)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProposalData {
pub status: ProposalStatus,
pub amount_approved: Amount,
}
4 changes: 4 additions & 0 deletions lib-blockchain/src/contracts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub mod emergency_reserve;
#[cfg(feature = "contracts")]
pub mod dao_registry;
#[cfg(feature = "contracts")]
pub mod dev_grants;
#[cfg(feature = "contracts")]
pub mod sov_swap;
#[cfg(feature = "contracts")]
pub mod utils;
Expand Down Expand Up @@ -71,6 +73,8 @@ pub use emergency_reserve::EmergencyReserve;
#[cfg(feature = "contracts")]
pub use dao_registry::{DAORegistry, DAOEntry, derive_dao_id};
#[cfg(feature = "contracts")]
pub use dev_grants::{DevelopmentGrants, ProposalId, Amount, Recipient, Disbursement};
#[cfg(feature = "contracts")]
pub use sov_swap::{SovSwapPool, SwapDirection, SwapResult, PoolState, SwapError};
#[cfg(feature = "contracts")]
pub use utils::*;
Expand Down
Loading
Loading