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
11 changes: 11 additions & 0 deletions soroban/contracts/factory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ const MIN_STAKE_AMOUNT: i128 = 1_000_000;
// Minimum lock period in ledgers required to prevent flash-loan-style attacks.
const MIN_LOCK_PERIOD: u32 = 1;

/// Mirror of `farming_pool::MAX_MIN_LOCK_PERIOD`: the factory rejects any
/// `min_lock_period` above this ceiling in `create_pool` before deploying a
/// pool, consistent with the pool-side check in `initialize`. See #132.
///
/// `2 years × 365 × 86_400 s/day / 5 s/ledger = 12_614_400 ledgers`.
const MAX_MIN_LOCK_PERIOD: u32 = 12_614_400; // ~2 years at 5 s/ledger

/// Convert a "credits per day" figure into the deployed pool's native
/// "credits per ledger" `credit_rate`.
///
Expand Down Expand Up @@ -1086,6 +1093,10 @@ impl Factory {
if min_lock_period < MIN_LOCK_PERIOD {
return Err(FactoryError::MinLockPeriodTooShort);
}
// Mirror the farming-pool ceiling — see #132.
if min_lock_period > MAX_MIN_LOCK_PERIOD {
return Err(FactoryError::MinLockPeriodAboveCeiling);
}
let effective_min_stake = if min_stake_amount <= 0 {
MIN_STAKE_AMOUNT
} else {
Expand Down
32 changes: 32 additions & 0 deletions soroban/contracts/factory/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,38 @@ fn test_create_pool_rejects_min_lock_period_out_of_u32_range() {
assert_eq!(result, Err(Ok(FactoryError::MinLockPeriodOutOfRange)));
}

// ── #132: factory-side upper ceiling on min_lock_period ───────────────────────

#[test]
fn test_create_pool_rejects_min_lock_period_above_ceiling() {
let t = setup();
let asset = Address::generate(&t.env);

// MAX_MIN_LOCK_PERIOD + 1, still fits in u32 (12_614_401 << u32::MAX), so
// the u32-range check passes and only the new ceiling check fires.
let above_ceiling = (MAX_MIN_LOCK_PERIOD + 1) as u64;
let result = t
.client
.try_create_pool(&asset, &1_728_000u128, &2u32, &above_ceiling, &0i128);
assert_eq!(result, Err(Ok(FactoryError::MinLockPeriodAboveCeiling)));
}

#[test]
fn test_create_pool_accepts_min_lock_period_exactly_at_ceiling() {
let t = setup();
let asset = Address::generate(&t.env);

let pool_id = t.client.create_pool(
&asset,
&1_728_000u128,
&2u32,
&(MAX_MIN_LOCK_PERIOD as u64),
&0i128,
);
let record = t.client.get_pool(&pool_id);
assert_eq!(record.min_lock_period, MAX_MIN_LOCK_PERIOD);
}

#[test]
fn test_get_pool_bumps_pool_record_ttl() {
let t = setup();
Expand Down
2 changes: 2 additions & 0 deletions soroban/contracts/factory/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,6 @@ pub enum FactoryError {
/// deployed pool did not answer the `total_staked` getter (e.g. a pool
/// deployed from an older WASM that predates it).
PoolQueryFailed = 17,
/// `create_pool`'s `min_lock_period` exceeded `MAX_MIN_LOCK_PERIOD`. See #132.
MinLockPeriodAboveCeiling = 18,
}
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,33 @@
},
"live_until": 1036800
},
{
"entry": {
"last_modified_ledger_seq": 0,
"data": {
"contract_data": {
"ext": "v0",
"contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
"key": {
"vec": [
{
"symbol": "PoolTvl"
},
{
"u32": 0
}
]
},
"durability": "persistent",
"val": {
"i128": "0"
}
}
},
"ext": "v0"
},
"live_until": 1036800
},
{
"entry": {
"last_modified_ledger_seq": 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,33 @@
},
"live_until": 1036800
},
{
"entry": {
"last_modified_ledger_seq": 0,
"data": {
"contract_data": {
"ext": "v0",
"contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM",
"key": {
"vec": [
{
"symbol": "PoolTvl"
},
{
"u32": 0
}
]
},
"durability": "persistent",
"val": {
"i128": "0"
}
}
},
"ext": "v0"
},
"live_until": 1036800
},
{
"entry": {
"last_modified_ledger_seq": 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,33 @@
},
"live_until": 1036800
},
{
"entry": {
"last_modified_ledger_seq": 0,
"data": {
"contract_data": {
"ext": "v0",
"contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
"key": {
"vec": [
{
"symbol": "PoolTvl"
},
{
"u32": 0
}
]
},
"durability": "persistent",
"val": {
"i128": "0"
}
}
},
"ext": "v0"
},
"live_until": 1036800
},
{
"entry": {
"last_modified_ledger_seq": 0,
Expand Down
Loading