Problem
Several private helpers call unwrap() on storage reads that have no fallback:
fn get_admin(env: &Env) -> Address {
env.storage().instance().get(&DataKey::Admin).unwrap() // panics if uninitialized
}
fn get_stake_token(env: &Env) -> Address {
env.storage().instance().get(&DataKey::StakeToken).unwrap() // panics if uninitialized
}
If any public function (e.g. stake, lock_assets, pause) is called before initialize, the contract panics with an opaque XDR host error instead of returning a typed PoolError::NotInitialized.
This also means any function that calls get_admin or get_stake_token internally has an implicit panic path that is not visible in the function signature.
Impact
- Denial of service: a misconfigured deployment (where init is not called — see issue #11) causes every subsequent call to panic, and there is no recovery without redeploying
- Poor debuggability: host panics produce opaque error codes;
PoolError::NotInitialized produces a readable, matchable error
Fix
Add an initialization guard function and replace all unwrap() in production paths:
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<Address, PoolError> {
env.storage().instance().get(&DataKey::Admin)
.ok_or(PoolError::NotInitialized)
}
All public functions should call require_initialized(&env)? as the first line (after auth where applicable).
Acceptance Criteria
Problem
Several private helpers call
unwrap()on storage reads that have no fallback:If any public function (e.g.
stake,lock_assets,pause) is called beforeinitialize, the contract panics with an opaque XDR host error instead of returning a typedPoolError::NotInitialized.This also means any function that calls
get_adminorget_stake_tokeninternally has an implicit panic path that is not visible in the function signature.Impact
PoolError::NotInitializedproduces a readable, matchable errorFix
Add an initialization guard function and replace all
unwrap()in production paths:All public functions should call
require_initialized(&env)?as the first line (after auth where applicable).Acceptance Criteria
require_initializedguard addedget_adminandget_stake_tokenreturnResult, notTrequire_initializedbefore any logicstakeon uninitialized contract returnsErr(PoolError::NotInitialized)pauseon uninitialized contract returnsErr(PoolError::NotInitialized)unwrap()in any non-test code path