diff --git a/soroban/contracts/farming-pool/src/lib.rs b/soroban/contracts/farming-pool/src/lib.rs index 5baf153..1a76e1b 100644 --- a/soroban/contracts/farming-pool/src/lib.rs +++ b/soroban/contracts/farming-pool/src/lib.rs @@ -2,6 +2,8 @@ mod types; +use soroban_sdk::{contract, contractimpl, symbol_short, token, Address, Env}; +use types::{BoostConfig, DataKey, PoolError, Position, UserStake}; use soroban_sdk::{ contract, contractimpl, symbol_short, token, Address, Env, }; @@ -26,8 +28,18 @@ fn bump_user(env: &Env, key: &DataKey) { .extend_ttl(key, USER_TTL_THRESHOLD, USER_TTL_EXTEND_TO); } -fn get_admin(env: &Env) -> Address { - env.storage().instance().get(&DataKey::Admin).unwrap() +fn require_initialized(env: &Env) -> Result<(), PoolError> { + if !env.storage().instance().has(&DataKey::Admin) { + return Err(PoolError::NotInitialized); + } + Ok(()) +} + +fn get_admin(env: &Env) -> Result { + env.storage() + .instance() + .get(&DataKey::Admin) + .ok_or(PoolError::NotInitialized) } fn get_global_multiplier(env: &Env) -> u32 { @@ -44,8 +56,11 @@ fn get_credit_rate(env: &Env) -> i128 { .unwrap_or(1) } -fn get_stake_token(env: &Env) -> Address { - env.storage().instance().get(&DataKey::StakeToken).unwrap() +fn get_stake_token(env: &Env) -> Result { + env.storage() + .instance() + .get(&DataKey::StakeToken) + .ok_or(PoolError::NotInitialized) } fn get_min_lock_period(env: &Env) -> u32 { @@ -156,7 +171,8 @@ fn checkpoint(env: &Env, user: &Address, stake: &mut UserStake) { let rate = get_credit_rate(env); let current = env.ledger().sequence(); let elapsed = current.saturating_sub(stake.start_ledger); - stake.credits_banked += compute_credits(stake.amount, allocation_pct, multiplier, rate, elapsed); + stake.credits_banked += + compute_credits(stake.amount, allocation_pct, multiplier, rate, elapsed); stake.start_ledger = current; } @@ -188,19 +204,28 @@ impl FarmingPool { global_multiplier: u32, credit_rate: i128, min_lock_period: u32, - ) { + ) -> Result<(), PoolError> { if env.storage().instance().has(&DataKey::Admin) { - panic!("already initialized"); + return Err(PoolError::AlreadyInitialized); } assert!(global_multiplier >= 1, "multiplier must be >= 1"); assert!(credit_rate > 0, "credit_rate must be positive"); env.storage().instance().set(&DataKey::Admin, &admin); - env.storage().instance().set(&DataKey::StakeToken, &stake_token); - env.storage().instance().set(&DataKey::GlobalMultiplier, &global_multiplier); - env.storage().instance().set(&DataKey::CreditRate, &credit_rate); - env.storage().instance().set(&DataKey::MinLockPeriod, &min_lock_period); + env.storage() + .instance() + .set(&DataKey::StakeToken, &stake_token); + env.storage() + .instance() + .set(&DataKey::GlobalMultiplier, &global_multiplier); + env.storage() + .instance() + .set(&DataKey::CreditRate, &credit_rate); + env.storage() + .instance() + .set(&DataKey::MinLockPeriod, &min_lock_period); bump_instance(&env); + Ok(()) } // ── Lock / Unlock system ───────────────────────────────────────────────── @@ -209,8 +234,9 @@ impl FarmingPool { /// checkpointed first and the new amount is added to the existing position. /// /// Emits a `("pool", "locked")` event with `(user, amount)`. - pub fn lock_assets(env: Env, user: Address, amount: i128) { + pub fn lock_assets(env: Env, user: Address, amount: i128) -> Result<(), PoolError> { user.require_auth(); + require_initialized(&env)?; assert!(!pool_is_paused(&env), "pool is paused"); assert!(amount > 0, "amount must be positive"); bump_instance(&env); @@ -229,8 +255,12 @@ impl FarmingPool { } }; - token::TokenClient::new(&env, &get_stake_token(&env)) - .transfer(&user, &env.current_contract_address(), &amount); + let stake_token = get_stake_token(&env)?; + token::TokenClient::new(&env, &stake_token).transfer( + &user, + &env.current_contract_address(), + &amount, + ); set_position(&env, &user, &pos); @@ -238,6 +268,7 @@ impl FarmingPool { (symbol_short!("pool"), symbol_short!("locked")), (user, amount), ); + Ok(()) } /// Unlock `amount` tokens for the caller. The minimum lock period (in ledgers) must @@ -245,8 +276,9 @@ impl FarmingPool { /// remaining balance stays locked. /// /// Emits a `("pool", "unlocked")` event with `(user, amount, total_credits)`. - pub fn unlock_assets(env: Env, user: Address, amount: i128) { + pub fn unlock_assets(env: Env, user: Address, amount: i128) -> Result<(), PoolError> { user.require_auth(); + require_initialized(&env)?; assert!(!pool_is_paused(&env), "pool is paused"); assert!(amount > 0, "amount must be positive"); bump_instance(&env); @@ -265,8 +297,12 @@ impl FarmingPool { let total_credits = pos.total_credits; pos.amount -= amount; - token::TokenClient::new(&env, &get_stake_token(&env)) - .transfer(&env.current_contract_address(), &user, &amount); + let stake_token = get_stake_token(&env)?; + token::TokenClient::new(&env, &stake_token).transfer( + &env.current_contract_address(), + &user, + &amount, + ); if pos.amount == 0 { remove_position(&env, &user); @@ -278,23 +314,29 @@ impl FarmingPool { (symbol_short!("pool"), symbol_short!("unlocked")), (user, amount, total_credits), ); + Ok(()) } /// Return total credits for `user` (banked + currently accruing). Returns 0 if no position. - pub fn calculate_credits(env: Env, user: Address) -> i128 { + pub fn calculate_credits(env: Env, user: Address) -> Result { + require_initialized(&env)?; bump_instance(&env); let Some(pos) = get_position(&env, &user) else { - return 0; + return Ok(0); }; let rate = get_credit_rate(&env); - let elapsed = env.ledger().sequence().saturating_sub(pos.checkpoint_ledger); - pos.total_credits + pos.amount * rate * elapsed as i128 + let elapsed = env + .ledger() + .sequence() + .saturating_sub(pos.checkpoint_ledger); + Ok(pos.total_credits + pos.amount * rate * elapsed as i128) } /// Return the current position for `user`, or `None` if no position exists. - pub fn get_user_position(env: Env, user: Address) -> Option { + pub fn get_user_position(env: Env, user: Address) -> Result, PoolError> { + require_initialized(&env)?; bump_instance(&env); - get_position(&env, &user) + Ok(get_position(&env, &user)) } // ── Pause / Unpause ─────────────────────────────────────────────────────── @@ -302,33 +344,34 @@ impl FarmingPool { /// Admin: pause the pool. While paused, `lock_assets` and `unlock_assets` are blocked. /// /// Emits a `("pool", "paused")` event. - pub fn pause(env: Env) { - get_admin(&env).require_auth(); + pub fn pause(env: Env) -> Result<(), PoolError> { + require_initialized(&env)?; + get_admin(&env)?.require_auth(); bump_instance(&env); env.storage().instance().set(&DataKey::Paused, &true); - env.events().publish( - (symbol_short!("pool"), symbol_short!("paused")), - (), - ); + env.events() + .publish((symbol_short!("pool"), symbol_short!("paused")), ()); + Ok(()) } /// Admin: unpause the pool, restoring normal operation. /// /// Emits a `("pool", "unpaused")` event. - pub fn unpause(env: Env) { - get_admin(&env).require_auth(); + pub fn unpause(env: Env) -> Result<(), PoolError> { + require_initialized(&env)?; + get_admin(&env)?.require_auth(); bump_instance(&env); env.storage().instance().set(&DataKey::Paused, &false); - env.events().publish( - (symbol_short!("pool"), symbol_short!("unpaused")), - (), - ); + env.events() + .publish((symbol_short!("pool"), symbol_short!("unpaused")), ()); + Ok(()) } /// Return whether the pool is currently paused. - pub fn is_paused(env: Env) -> bool { + pub fn is_paused(env: Env) -> Result { + require_initialized(&env)?; bump_instance(&env); - pool_is_paused(&env) + Ok(pool_is_paused(&env)) } /// Admin: return all tokens for `user` during an emergency. @@ -392,8 +435,9 @@ impl FarmingPool { // ── Boost / Stake system (unchanged) ───────────────────────────────────── /// Stake `amount` tokens. If a prior stake exists, earned credits are checkpointed first. - pub fn stake(env: Env, from: Address, amount: i128) { + pub fn stake(env: Env, from: Address, amount: i128) -> Result<(), PoolError> { from.require_auth(); + require_initialized(&env)?; assert!(amount > 0, "amount must be positive"); bump_instance(&env); @@ -411,15 +455,21 @@ impl FarmingPool { }; // Pull tokens from caller into the contract. - token::TokenClient::new(&env, &get_stake_token(&env)) - .transfer(&from, &env.current_contract_address(), &amount); + let stake_token = get_stake_token(&env)?; + token::TokenClient::new(&env, &stake_token).transfer( + &from, + &env.current_contract_address(), + &amount, + ); set_user_stake(&env, &from, &new_stake); + Ok(()) } /// Unstake all tokens. Returns the total credits earned. - pub fn unstake(env: Env, from: Address) -> i128 { + pub fn unstake(env: Env, from: Address) -> Result { from.require_auth(); + require_initialized(&env)?; bump_instance(&env); let mut stake = get_user_stake(&env, &from).expect("no active stake"); @@ -427,11 +477,15 @@ impl FarmingPool { let total_credits = stake.credits_banked; // Return staked tokens to caller. - token::TokenClient::new(&env, &get_stake_token(&env)) - .transfer(&env.current_contract_address(), &from, &stake.amount); + let stake_token = get_stake_token(&env)?; + token::TokenClient::new(&env, &stake_token).transfer( + &env.current_contract_address(), + &from, + &stake.amount, + ); remove_user_stake(&env, &from); - total_credits + Ok(total_credits) } /// Set the caller's boost allocation percentage (1–100%). @@ -440,8 +494,9 @@ impl FarmingPool { /// rewards are lost when the boost is updated. /// /// Emits a `boost_applied` event. - pub fn set_boost(env: Env, user: Address, allocation_pct: u32) { + pub fn set_boost(env: Env, user: Address, allocation_pct: u32) -> Result<(), PoolError> { user.require_auth(); + require_initialized(&env)?; assert!( allocation_pct >= 1 && allocation_pct <= 100, "allocation_pct must be 1–100" @@ -463,18 +518,22 @@ impl FarmingPool { (symbol_short!("boost"), symbol_short!("applied")), (user, allocation_pct, multiplier), ); + Ok(()) } /// Return the current boost configuration for `user`, or `None` if no boost is set. /// /// `BoostConfig.multiplier` reflects the current global multiplier. /// `BoostConfig.allocation_pct` is the user's chosen allocation. - pub fn get_boost_config(env: Env, user: Address) -> Option { + pub fn get_boost_config(env: Env, user: Address) -> Result, PoolError> { + require_initialized(&env)?; bump_instance(&env); - get_user_boost(&env, &user).map(|allocation_pct| BoostConfig { - multiplier: get_global_multiplier(&env), - allocation_pct, - }) + Ok( + get_user_boost(&env, &user).map(|allocation_pct| BoostConfig { + multiplier: get_global_multiplier(&env), + allocation_pct, + }), + ) } /// Admin: update the global boost multiplier. @@ -482,36 +541,43 @@ impl FarmingPool { /// Emits a `mult_set` event. Note that in-flight credits are not retroactively /// recalculated; the new multiplier applies from the next ledger onward for /// users whose boost configs are not checkpointed yet. - pub fn set_global_multiplier(env: Env, multiplier: u32) { - get_admin(&env).require_auth(); + pub fn set_global_multiplier(env: Env, multiplier: u32) -> Result<(), PoolError> { + require_initialized(&env)?; + get_admin(&env)?.require_auth(); assert!(multiplier >= 1, "multiplier must be >= 1"); bump_instance(&env); - env.storage().instance().set(&DataKey::GlobalMultiplier, &multiplier); + env.storage() + .instance() + .set(&DataKey::GlobalMultiplier, &multiplier); env.events().publish( (symbol_short!("boost"), symbol_short!("mult_set")), multiplier, ); + Ok(()) } /// Return total credits for `user` in the boost/stake system (banked + currently accruing). - pub fn get_credits(env: Env, user: Address) -> i128 { + pub fn get_credits(env: Env, user: Address) -> Result { + require_initialized(&env)?; bump_instance(&env); let Some(stake) = get_user_stake(&env, &user) else { - return 0; + return Ok(0); }; let allocation_pct = get_user_boost(&env, &user).unwrap_or(0); let multiplier = get_global_multiplier(&env); let rate = get_credit_rate(&env); let elapsed = env.ledger().sequence().saturating_sub(stake.start_ledger); - stake.credits_banked + compute_credits(stake.amount, allocation_pct, multiplier, rate, elapsed) + Ok(stake.credits_banked + + compute_credits(stake.amount, allocation_pct, multiplier, rate, elapsed)) } /// Return the current stake record for `user`, or `None` if not staked. - pub fn get_stake(env: Env, user: Address) -> Option { + pub fn get_stake(env: Env, user: Address) -> Result, PoolError> { + require_initialized(&env)?; bump_instance(&env); - get_user_stake(&env, &user) + Ok(get_user_stake(&env, &user)) } } diff --git a/soroban/contracts/farming-pool/src/test.rs b/soroban/contracts/farming-pool/src/test.rs index 4bb2a6a..8db358a 100644 --- a/soroban/contracts/farming-pool/src/test.rs +++ b/soroban/contracts/farming-pool/src/test.rs @@ -22,12 +22,31 @@ fn setup(global_multiplier: u32, credit_rate: i128) -> TestEnv { setup_with_lock_period(global_multiplier, credit_rate, 0) } -fn setup_with_lock_period(global_multiplier: u32, credit_rate: i128, min_lock_period: u32) -> TestEnv { +fn setup_uninitialized() -> (Env, FarmingPoolClient<'static>, Address) { + let env = Env::default(); + env.mock_all_auths(); + + let user = Address::generate(&env); + let contract_id = env.register(FarmingPool, ()); + let client = FarmingPoolClient::new(&env, &contract_id); + + let client = unsafe { + core::mem::transmute::, FarmingPoolClient<'static>>(client) + }; + + (env, client, user) +} + +fn setup_with_lock_period( + global_multiplier: u32, + credit_rate: i128, + min_lock_period: u32, +) -> TestEnv { let env = Env::default(); env.mock_all_auths(); let admin = Address::generate(&env); - let user = Address::generate(&env); + let user = Address::generate(&env); // Deploy a Stellar Asset Contract for the stake token. let token_admin = Address::generate(&env); @@ -37,7 +56,13 @@ fn setup_with_lock_period(global_multiplier: u32, credit_rate: i128, min_lock_pe let contract_id = env.register(FarmingPool, ()); let client = FarmingPoolClient::new(&env, &contract_id); - client.initialize(&admin, &asset.address(), &global_multiplier, &credit_rate, &min_lock_period); + client.initialize( + &admin, + &asset.address(), + &global_multiplier, + &credit_rate, + &min_lock_period, + ); let token = TokenClient::new(&env, &asset.address()); @@ -46,14 +71,19 @@ fn setup_with_lock_period(global_multiplier: u32, credit_rate: i128, min_lock_pe let client = unsafe { core::mem::transmute::, FarmingPoolClient<'static>>(client) }; - let token = unsafe { - core::mem::transmute::, TokenClient<'static>>(token) - }; + let token = unsafe { core::mem::transmute::, TokenClient<'static>>(token) }; let token_sac = unsafe { core::mem::transmute::, StellarAssetClient<'static>>(token_sac) }; - TestEnv { env, client, token, token_sac, admin, user } + TestEnv { + env, + client, + token, + token_sac, + admin, + user, + } } fn advance_ledgers(env: &Env, by: u32) { @@ -61,6 +91,24 @@ fn advance_ledgers(env: &Env, by: u32) { env.ledger().with_mut(|l| l.sequence_number = current + by); } +#[test] +fn test_stake_uninitialized_returns_not_initialized() { + let (_env, client, user) = setup_uninitialized(); + match client.try_stake(&user, &100i128) { + Err(Ok(PoolError::NotInitialized)) => {} + _ => panic!("expected PoolError::NotInitialized"), + } +} + +#[test] +fn test_pause_uninitialized_returns_not_initialized() { + let (_env, client, _user) = setup_uninitialized(); + match client.try_pause() { + Err(Ok(PoolError::NotInitialized)) => {} + _ => panic!("expected PoolError::NotInitialized"), + } +} + // ── Boost calculation unit tests ────────────────────────────────────────────── #[test] @@ -107,7 +155,10 @@ fn test_set_boost_and_get_config() { t.client.stake(&t.user, &1_000); t.client.set_boost(&t.user, &50u32); - let cfg = t.client.get_boost_config(&t.user).expect("boost config should be set"); + let cfg = t + .client + .get_boost_config(&t.user) + .expect("boost config should be set"); assert_eq!(cfg.allocation_pct, 50); assert_eq!(cfg.multiplier, 2); } @@ -268,7 +319,10 @@ fn test_lock_assets_creates_position() { let initial_balance = t.token.balance(&t.user); t.client.lock_assets(&t.user, &500); - let pos = t.client.get_user_position(&t.user).expect("position should exist"); + let pos = t + .client + .get_user_position(&t.user) + .expect("position should exist"); assert_eq!(pos.amount, 500); assert_eq!(pos.total_credits, 0); assert_eq!(t.token.balance(&t.user), initial_balance - 500); @@ -283,7 +337,10 @@ fn test_lock_assets_additional_lock_checkpoints_credits() { advance_ledgers(&t.env, 10); t.client.lock_assets(&t.user, &500); // triggers checkpoint - let pos = t.client.get_user_position(&t.user).expect("position should exist"); + let pos = t + .client + .get_user_position(&t.user) + .expect("position should exist"); assert_eq!(pos.amount, 1_500); assert_eq!(pos.total_credits, 10_000); // 1000 * 10 } @@ -304,14 +361,20 @@ fn test_lock_assets_rejects_negative_amount() { fn test_lock_assets_rejects_insufficient_balance() { let t = setup(1, 1); // User only has 1_000_000_000 tokens; try to lock more. - assert!(t.client.try_lock_assets(&t.user, &2_000_000_000i128).is_err()); + assert!(t + .client + .try_lock_assets(&t.user, &2_000_000_000i128) + .is_err()); } #[test] fn test_lock_assets_emits_event() { let t = setup(1, 1); t.client.lock_assets(&t.user, &1_000); - assert!(!t.env.events().all().events().is_empty(), "lock event not emitted"); + assert!( + !t.env.events().all().events().is_empty(), + "lock event not emitted" + ); } // ── unlock_assets tests ─────────────────────────────────────────────────────── @@ -340,7 +403,10 @@ fn test_unlock_assets_partial_keeps_remaining_position() { t.client.unlock_assets(&t.user, &400); // partial unlock - let pos = t.client.get_user_position(&t.user).expect("position should still exist"); + let pos = t + .client + .get_user_position(&t.user) + .expect("position should still exist"); assert_eq!(pos.amount, 600); // 1000 * 10 = 10000 credits banked during checkpoint assert_eq!(pos.total_credits, 10_000); @@ -373,7 +439,10 @@ fn test_unlock_assets_emits_event() { t.client.lock_assets(&t.user, &1_000); advance_ledgers(&t.env, 5); t.client.unlock_assets(&t.user, &1_000); - assert!(!t.env.events().all().events().is_empty(), "unlock event not emitted"); + assert!( + !t.env.events().all().events().is_empty(), + "unlock event not emitted" + ); } // ── minimum lock period tests ───────────────────────────────────────────────── @@ -391,7 +460,7 @@ fn test_unlock_allowed_after_min_lock_period() { let t = setup_with_lock_period(1, 1, 100); t.client.lock_assets(&t.user, &1_000); advance_ledgers(&t.env, 100); // exactly at the boundary - // Should succeed — no panic. + // Should succeed — no panic. t.client.unlock_assets(&t.user, &1_000); assert!(t.client.get_user_position(&t.user).is_none()); } @@ -515,7 +584,10 @@ fn test_unpause_restores_operations() { fn test_pause_emits_event() { let t = setup(1, 1); t.client.pause(); - assert!(!t.env.events().all().events().is_empty(), "pause event not emitted"); + assert!( + !t.env.events().all().events().is_empty(), + "pause event not emitted" + ); } #[test] @@ -523,7 +595,10 @@ fn test_unpause_emits_event() { let t = setup(1, 1); t.client.pause(); t.client.unpause(); - assert!(!t.env.events().all().events().is_empty(), "unpause event not emitted"); + assert!( + !t.env.events().all().events().is_empty(), + "unpause event not emitted" + ); } // ── multi-user isolation ────────────────────────────────────────────────────── @@ -540,7 +615,7 @@ fn test_multiple_users_independent_positions() { // Each user's credits are independent. assert_eq!(t.client.calculate_credits(&t.user), 10_000); // 1000 * 10 - assert_eq!(t.client.calculate_credits(&user2), 20_000); // 2000 * 10 + assert_eq!(t.client.calculate_credits(&user2), 20_000); // 2000 * 10 } #[test] @@ -556,7 +631,10 @@ fn test_one_user_unlock_does_not_affect_another() { t.client.unlock_assets(&t.user, &1_000); // user2's position is untouched. - let pos2 = t.client.get_user_position(&user2).expect("user2 position should exist"); + let pos2 = t + .client + .get_user_position(&user2) + .expect("user2 position should exist"); assert_eq!(pos2.amount, 2_000); } diff --git a/soroban/contracts/farming-pool/src/types.rs b/soroban/contracts/farming-pool/src/types.rs index 6cf1ae0..513e1bf 100644 --- a/soroban/contracts/farming-pool/src/types.rs +++ b/soroban/contracts/farming-pool/src/types.rs @@ -1,5 +1,14 @@ use soroban_sdk::{contracterror, contracttype, Address}; +/// Typed errors returned by the farming pool contract. +#[contracterror] +#[derive(Copy, Clone, Debug, PartialEq)] +#[repr(u32)] +pub enum PoolError { + AlreadyInitialized = 1, + NotInitialized = 2, +} + /// Per-user boost configuration returned by `get_boost_config`. /// `multiplier` is the current global multiplier set by the admin. /// `allocation_pct` is the percentage of the user's stake allocated to boosted earning (1-100). diff --git a/soroban/contracts/farming-pool/test_snapshots/test/test_pause_uninitialized_returns_not_initialized.1.json b/soroban/contracts/farming-pool/test_snapshots/test/test_pause_uninitialized_returns_not_initialized.1.json new file mode 100644 index 0000000..9210941 --- /dev/null +++ b/soroban/contracts/farming-pool/test_snapshots/test/test_pause_uninitialized_returns_not_initialized.1.json @@ -0,0 +1,61 @@ +{ + "generators": { + "address": 2, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [] + ], + "ledger": { + "protocol_version": 25, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/soroban/contracts/farming-pool/test_snapshots/test/test_stake_uninitialized_returns_not_initialized.1.json b/soroban/contracts/farming-pool/test_snapshots/test/test_stake_uninitialized_returns_not_initialized.1.json new file mode 100644 index 0000000..9210941 --- /dev/null +++ b/soroban/contracts/farming-pool/test_snapshots/test/test_stake_uninitialized_returns_not_initialized.1.json @@ -0,0 +1,61 @@ +{ + "generators": { + "address": 2, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [] + ], + "ledger": { + "protocol_version": 25, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file