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
6 changes: 6 additions & 0 deletions soroban-contracts/contracts/single_rwa_vault/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ pub enum Error {
/// Burn requires pending yield to be claimed first (Option A).
BurnRequiresYieldClaim = 32,
InvalidDepositLimits = 33,
/// Shares are still within lock-up period and cannot be transferred
SharesLocked = 34,
/// Vault has insufficient balance to cover the requested transfer
InsufficientVaultBalance = 35,
/// Maximum number of investors has been reached
MaxInvestorsReached = 36,
/// Timelock action not found or invalid.
TimelockActionNotFound = 34,
/// Timelock delay has not passed yet.
Expand Down
271 changes: 248 additions & 23 deletions soroban-contracts/contracts/single_rwa_vault/src/lib.rs

Large diffs are not rendered by default.

66 changes: 48 additions & 18 deletions soroban-contracts/contracts/single_rwa_vault/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ pub enum Key {
ExpApy,

// --- Vault config ---
FundTgt,
MatDate,
MinDep,
MaxDepUsr,
ERedFee,
/// Yield vesting period in seconds (0 = instant claiming for backward compatibility)
YldVstPer,
FundingTarget,
MaturityDate,
MinDeposit,
MaxDepositPerUser,
MaxInvestors,
EarlyRedemptionFeeBps,
LockUpPeriod,

// --- Vault state ---
VaultSt,
Expand Down Expand Up @@ -106,11 +106,15 @@ pub enum Key {
TotSup,

// --- User deposit tracking ---
UsrDep(Address),
UserDeposited(Address),
DepositTimestamp(Address),

// --- Total deposited principal ---
TotDep,

// --- Investor tracking ---
InvestorCount,

// --- Early redemption ---
RedCnt,
RedReq(u32),
Expand Down Expand Up @@ -469,18 +473,23 @@ pub fn put_funding_deadline(e: &Env, val: u64) {
e.storage().instance().set(&Key::FundDeadl, &val);
}

instance_get!(get_min_deposit, MinDep, i128);
instance_put!(put_min_deposit, MinDep, i128);
instance_get!(get_max_deposit_per_user, MaxDepUsr, i128);
instance_put!(put_max_deposit_per_user, MaxDepUsr, i128);
instance_get!(get_early_redemption_fee_bps, ERedFee, u32);
instance_put!(put_early_redemption_fee_bps, ERedFee, u32);
instance_get!(get_min_deposit, MinDeposit, i128);
instance_put!(put_min_deposit, MinDeposit, i128);
instance_get!(get_max_deposit_per_user, MaxDepositPerUser, i128);
instance_put!(put_max_deposit_per_user, MaxDepositPerUser, i128);
instance_get!(get_max_investors, MaxInvestors, u32);
instance_put!(put_max_investors, MaxInvestors, u32);
instance_get!(get_early_redemption_fee_bps, EarlyRedemptionFeeBps, u32);
instance_put!(put_early_redemption_fee_bps, EarlyRedemptionFeeBps, u32);

pub fn get_yield_vesting_period(e: &Env) -> u64 {
e.storage().instance().get(&Key::YldVstPer).unwrap_or(0) // Default to 0 for backward compatibility (instant claiming)
pub fn get_lock_up_period(e: &Env) -> u64 {
e.storage()
.instance()
.get(&DataKey::LockUpPeriod)
.unwrap_or(0)
}
pub fn put_yield_vesting_period(e: &Env, val: u64) {
e.storage().instance().set(&Key::YldVstPer, &val);
pub fn put_lock_up_period(e: &Env, val: u64) {
e.storage().instance().set(&DataKey::LockUpPeriod, &val);
}

// State
Expand Down Expand Up @@ -514,6 +523,10 @@ instance_put!(put_total_supply, TotSup, i128);
instance_get!(get_total_deposited, TotDep, i128);
instance_put!(put_total_deposited, TotDep, i128);

// InvestorCount (unique investor tracking)
instance_get!(get_investor_count, InvestorCount, u32);
instance_put!(put_investor_count, InvestorCount, u32);

// RedemptionCounter
instance_get!(get_redemption_counter, RedCnt, u32);
instance_put!(put_redemption_counter, RedCnt, u32);
Expand Down Expand Up @@ -723,6 +736,23 @@ pub fn put_user_deposited(e: &Env, addr: &Address, val: i128) {
);
}

pub fn get_deposit_timestamp(e: &Env, addr: &Address) -> u64 {
e.storage()
.persistent()
.get(&DataKey::DepositTimestamp(addr.clone()))
.unwrap_or(0)
}
pub fn put_deposit_timestamp(e: &Env, addr: &Address, val: u64) {
e.storage()
.persistent()
.set(&DataKey::DepositTimestamp(addr.clone()), &val);
e.storage().persistent().extend_ttl(
&DataKey::DepositTimestamp(addr.clone()),
BALANCE_LIFETIME_THRESHOLD,
BALANCE_BUMP_AMOUNT,
);
}

pub fn get_total_yield_claimed(e: &Env, addr: &Address) -> i128 {
e.storage()
.persistent()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ fn get_valid_params(e: &Env) -> InitParams {
funding_deadline: 0,
min_deposit: 10,
max_deposit_per_user: 100,
max_investors: 100,
early_redemption_fee_bps: 200,
rwa_name: String::from_str(e, "RWA"),
rwa_symbol: String::from_str(e, "R"),
rwa_document_uri: String::from_str(e, "uri"),
rwa_category: String::from_str(e, "cat"),
expected_apy: 500,
timelock_delay: 172800u64, // 48 hours
yield_vesting_period: 0u64,
lock_up_period: 0u64,
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,13 +264,13 @@ fn default_params(
funding_deadline: 9_999_999_999u64, // far future (no effective deadline by default)
min_deposit: 1_000_000i128, // 1 USDC
max_deposit_per_user: 0i128, // unlimited
max_investors: 100u32, // reasonable default for tests
early_redemption_fee_bps: 200u32, // 2 %
rwa_name: String::from_str(env, "US Treasury Bond 2026"),
rwa_symbol: String::from_str(env, "USTB26"),
rwa_document_uri: String::from_str(env, "https://example.com/ustb26"),
rwa_category: String::from_str(env, "Government Bond"),
expected_apy: 500u32, // 5 %
timelock_delay: 172800u64, // 48 hours
yield_vesting_period: 0u64, // Default to 0 for instant claiming (backward compatibility)
expected_apy: 500u32, // 5 %
lock_up_period: 0u64, // no lock-up by default
}
}
Loading
Loading