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
22 changes: 1 addition & 21 deletions Contract/rewards/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,27 +336,7 @@ impl RewardsContract {
.unwrap_or(0);
Ok(count)
}
}


pub fn initialize_rewards(_env: Env, _total_pool: i128, _reward_asset: Asset) {
todo!("Implement rewards initialization")
}

pub fn claim_rewards(_env: Env, _user: Address) -> i128 {
todo!("Implement reward claiming")
}

pub fn grant_reward(_env: Env, _recipient: Address, _amount: i128, _reward_type: u32) {
todo!("Implement reward granting")
}

pub fn get_pending_rewards(_env: Env, _user: Address) -> i128 {
todo!("Implement pending rewards calculation")
}

pub fn calculate_streak_bonus(_env: Env, _streak_count: u32) -> u32 {
todo!("Implement streak bonus calculation")
/// Initialize the rewards system with admin and reward asset
/// Can only be called once
pub fn initialize(env: Env, admin: Address, reward_asset: BytesN<32>, streaks_contract: Address) {
Expand Down Expand Up @@ -707,4 +687,4 @@ impl RewardsContract {
let key = Self::rewards_storage_key(env);
env.storage().persistent().set(&key, &rewards);
}
}
}
77 changes: 14 additions & 63 deletions Contract/shared/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,90 +23,41 @@ pub enum Error {
LiquidationThreshold = 16,
RewardAlreadyClaimed = 17,
InvalidParameters = 18,

/// Pool not found - the specified lending pool does not exist
PoolNotFound = 19,

/// Pool already exists - a pool for this asset already exists
PoolAlreadyExists = 20,

/// Insufficient liquidity - not enough available liquidity for operation
InsufficientLiquidity = 21,

/// Invalid interest rate - interest rate outside allowed bounds
InvalidInterestRate = 22,

/// Invalid share amount - share amount must be positive
InvalidShareAmount = 23,

/// Pool paused - operation not allowed while pool is paused
PoolPaused = 24,

/// Pool closed - operation not allowed on closed pool
PoolClosed = 25,

/// Zero shares - cannot withdraw zero shares
ZeroShares = 26,

/// Insufficient shares - not enough shares for withdrawal
InsufficientShares = 27,

/// Invalid reserve factor - reserve factor outside allowed bounds
InvalidReserveFactor = 28,

/// Rate limit exceeded - operation rate limit reached
RateLimitExceeded = 29,

/// Emergency stop active - operation blocked due to emergency stop
EmergencyStopActive = 30,

/// Permission denied - insufficient permissions for operation
PermissionDenied = 31,

/// Loan already exists - loan ID already in use
LoanAlreadyExists = 32,

/// Invalid collateral - collateral asset not supported or insufficient
InvalidCollateral = 33,

/// Collateral ratio too low - position undercollateralized
CollateralRatioTooLow = 34,

/// Flash loan not allowed - flash loans disabled for this pool
FlashLoanNotAllowed = 35,

/// Cooldown period not met - operation blocked by cooldown
CooldownPeriodNotMet = 36,

/// Invalid timestamp - timestamp outside acceptable range
InvalidTimestampRange = 37,

/// Contract paused - operation blocked due to paused state
ContractPaused = 38,

/// Reentrancy detected - potential reentrancy attack blocked
ReentrancyDetected = 39,

/// Invalid signature - signature verification failed
InvalidSignature = 40,

/// Expired deadline - operation deadline has passed
ExpiredDeadline = 41,
StorageExpired = 42,
DuplicateActivity = 43,
NoFreezesAvailable = 44,
MilestoneAlreadyReached = 45,
RewardsPoolNotInitialized = 46,
RewardsPoolAlreadyInitialized = 47,
InsufficientRewardLiquidity = 48,
UnauthorizedAdmin = 49,
RewardNotEligible = 50,
PoolAlreadyInitialized = 51,
LoanAlreadyRepaid = 52,
LiquidationNotAllowed = 53,
NoPositionFound = 54,
}
DuplicateActivity = 19,
NoFreezesAvailable = 20,
MilestoneAlreadyReached = 21,
RewardsPoolNotInitialized = 22,
RewardsPoolAlreadyInitialized = 23,
InsufficientRewardLiquidity = 24,
UnauthorizedAdmin = 25,
RewardNotEligible = 26,
InvalidInterestRate = 27,
PoolNotFound = 28,
PoolAlreadyInitialized = 29,
LoanAlreadyExists = 30,
LoanAlreadyRepaid = 31,
LiquidationNotAllowed = 32,
NoPositionFound = 33,
InsufficientShares = 34,
}

193 changes: 184 additions & 9 deletions Contract/shared/src/storage.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,195 @@
use soroban_sdk::{BytesN, Env};
use crate::errors::Error;
use soroban_sdk::{BytesN, Env, IntoVal, Val};

/// Storage key type for persistent storage
/// Shared storage key type for raw byte-based maps
pub type StorageKey = BytesN<32>;

/// Simple storage helpers for common operations
/// Contracts should use direct storage operations for complex types
/// -------------------------------------------------------------------------
/// TTL POLICY
/// -------------------------------------------------------------------------
///
/// Soroban persistent storage expires unless its TTL is periodically extended.
///
/// Every protocol record should renew its TTL whenever it is:
///
/// - created
/// - read
/// - modified
///
/// This helper centralizes the TTL policy for every Vaulty contract.
/// -------------------------------------------------------------------------

pub struct StorageTTL;

/// Ledger estimates (~5 seconds/ledger)
impl StorageTTL {
/// ≈ 1 day
pub const DAY: u32 = 17_280;

/// ≈ 30 days
pub const MONTH: u32 = Self::DAY * 30;

/// ≈ 1 year
pub const YEAR: u32 = Self::DAY * 365;

/// Safety buffer before expiration
pub const BUFFER: u32 = Self::MONTH;

/// ---------------------------------------------------------------------
/// TTL categories
/// ---------------------------------------------------------------------

/// Contract instance storage
pub const INSTANCE: u32 = Self::YEAR;

/// Vault metadata
pub const VAULT: u32 = Self::YEAR * 6;

/// User balances
pub const USER: u32 = Self::YEAR * 6;

/// Reward state
pub const REWARD: u32 = Self::YEAR * 3;

/// Lending pools
pub const LENDING: u32 = Self::YEAR * 6;

/// Borrow positions
pub const BORROWING: u32 = Self::YEAR * 6;

/// Streak records
pub const STREAK: u32 = Self::YEAR * 6;
}

/// Storage helpers
pub struct StorageHelper;

impl StorageHelper {
/// Check if a key exists in persistent storage
pub fn has(env: &Env, key: &BytesN<32>) -> bool {
/// ---------------------------------------------------------------------
/// Basic helpers
/// ---------------------------------------------------------------------

pub fn has<K>(env: &Env, key: &K) -> bool
where
K: soroban_sdk::IntoVal<Env, soroban_sdk::Val> + ?Sized,
{
env.storage().persistent().has(key)
}

/// Check if a key exists in instance storage
pub fn has_instance(env: &Env, key: &BytesN<32>) -> bool {
pub fn has_instance<K>(env: &Env, key: &K) -> bool
where
K: soroban_sdk::IntoVal<Env, soroban_sdk::Val> + ?Sized,
{
env.storage().instance().has(key)
}
}

/// ---------------------------------------------------------------------
/// Persistent TTL
/// ---------------------------------------------------------------------

pub fn extend_persistent<K>(
env: &Env,
key: &K,
threshold: u32,
extend_to: u32,
)
where
K: soroban_sdk::IntoVal<Env, soroban_sdk::Val> + ?Sized,
{
env.storage()
.persistent()
.extend_ttl(key, threshold, extend_to);
}

pub fn ensure_persistent_not_expired<K>(
env: &Env,
key: &K,
threshold: u32,
) -> Result<(), Error>
where
K: soroban_sdk::IntoVal<Env, soroban_sdk::Val> + ?Sized,
{
if !env.storage().persistent().has(key) {
return Err(Error::NotInitialized);
}
env.storage()
.persistent()
.extend_ttl(key, threshold, threshold);
Ok(())
}

/// ---------------------------------------------------------------------
/// Instance TTL
/// ---------------------------------------------------------------------

pub fn extend_instance(
env: &Env,
threshold: u32,
extend_to: u32,
) {
env.storage()
.instance()
.extend_ttl(threshold, extend_to);
}

/// ---------------------------------------------------------------------
/// Category helpers
/// ---------------------------------------------------------------------

pub fn touch<K>(env: &Env, key: &K, ttl: u32)
where
K: soroban_sdk::IntoVal<Env, soroban_sdk::Val> + ?Sized,
{
Self::extend_persistent(env, key, StorageTTL::BUFFER, ttl);
}

pub fn touch_vault<K>(env: &Env, key: &K)
where
K: soroban_sdk::IntoVal<Env, soroban_sdk::Val> + ?Sized,
{
Self::touch(env, key, StorageTTL::VAULT);
}

pub fn touch_user<K>(env: &Env, key: &K)
where
K: soroban_sdk::IntoVal<Env, soroban_sdk::Val> + ?Sized,
{
Self::touch(env, key, StorageTTL::USER);
}

pub fn touch_reward<K>(env: &Env, key: &K)
where
K: soroban_sdk::IntoVal<Env, soroban_sdk::Val> + ?Sized,
{
Self::touch(env, key, StorageTTL::REWARD);
}

pub fn touch_lending<K>(env: &Env, key: &K)
where
K: soroban_sdk::IntoVal<Env, soroban_sdk::Val> + ?Sized,
{
Self::touch(env, key, StorageTTL::LENDING);
}

pub fn touch_borrowing<K>(env: &Env, key: &K)
where
K: soroban_sdk::IntoVal<Env, soroban_sdk::Val> + ?Sized,
{
Self::touch(env, key, StorageTTL::BORROWING);
}

pub fn touch_streak<K>(env: &Env, key: &K)
where
K: soroban_sdk::IntoVal<Env, soroban_sdk::Val> + ?Sized,
{
Self::touch(env, key, StorageTTL::STREAK);
}

pub fn touch_instance(env: &Env) {
Self::extend_instance(
env,
StorageTTL::BUFFER,
StorageTTL::INSTANCE,
);
}
}
25 changes: 10 additions & 15 deletions Contract/shared/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@ pub enum PoolStatus {
RateLimited = 4,
}

/// Loan status for borrowing contract
/// Loan status shared by the lending/borrowing contracts.
///
/// NOTE: the uploaded repo defined this enum twice (once here with a
/// `Defaulted` variant used by the older `LoanInfo`-based borrowing draft,
/// and once later with only `Active`/`Repaid`/`Liquidated` used by the
/// newer `Loan`-based draft). Kept as one definition, since both drafts
/// only ever reference `Active`, `Repaid`, and `Liquidated` in practice.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[contracttype]
#[repr(u32)]
Expand Down Expand Up @@ -87,7 +93,7 @@ pub struct CollateralConfig {
pub safety_factor: i128, // Basis points
}

/// Loan information
/// Loan information (used by the older `LoanInfo`-based borrowing draft)
#[derive(Clone, Debug, PartialEq, Eq)]
#[contracttype]
pub struct LoanInfo {
Expand Down Expand Up @@ -188,17 +194,7 @@ pub struct PoolPosition {
pub last_accrued_at: u64,
}

/// Loan status for borrowing flows.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[contracttype]
#[repr(u32)]
pub enum LoanStatus {
Active = 0,
Repaid = 1,
Liquidated = 2,
}

/// Collateralized loan state.
/// Collateralized loan state (used by the newer `Loan`-based borrowing draft).
#[derive(Clone, Debug, PartialEq, Eq)]
#[contracttype]
pub struct Loan {
Expand Down Expand Up @@ -343,5 +339,4 @@ pub struct EmergencyStop {
pub triggered_by: Address,
pub triggered_at: u64,
pub reason: BytesN<32>,
}
}
}
Loading
Loading