diff --git a/backstop/src/contract.rs b/backstop/src/contract.rs
index 39434b90..3dcba7b2 100644
--- a/backstop/src/contract.rs
+++ b/backstop/src/contract.rs
@@ -207,7 +207,7 @@ impl Backstop for BackstopContract {
drop_list: Map
,
) {
storage::extend_instance(&e);
- if storage::has_backstop_token(&e) {
+ if storage::get_is_init(&e) {
panic_with_error!(e, BackstopError::AlreadyInitialized);
}
@@ -224,6 +224,8 @@ impl Backstop for BackstopContract {
let last_distribution_time =
EmitterClient::new(&e, &emitter).get_last_distro(&e.current_contract_address());
storage::set_last_distribution_time(&e, &last_distribution_time);
+
+ storage::set_is_init(&e);
}
/********** Core **********/
diff --git a/backstop/src/storage.rs b/backstop/src/storage.rs
index 4179eb9a..dea989c5 100644
--- a/backstop/src/storage.rs
+++ b/backstop/src/storage.rs
@@ -39,6 +39,7 @@ pub struct UserEmissionData {
/********** Storage Key Types **********/
+const IS_INIT_KEY: &str = "IsInit";
const EMITTER_KEY: &str = "Emitter";
const BACKSTOP_TOKEN_KEY: &str = "BToken";
const POOL_FACTORY_KEY: &str = "PoolFact";
@@ -97,7 +98,19 @@ fn get_persistent_default, V: TryFromVal>(
}
}
-/********** External Contracts **********/
+/********** Instance Storage **********/
+
+/// Check if the contract has been initialized
+pub fn get_is_init(e: &Env) -> bool {
+ e.storage().instance().has(&Symbol::new(e, IS_INIT_KEY))
+}
+
+/// Set the contract as initialized
+pub fn set_is_init(e: &Env) {
+ e.storage()
+ .instance()
+ .set::(&Symbol::new(e, IS_INIT_KEY), &true);
+}
/// Fetch the pool factory id
pub fn get_emitter(e: &Env) -> Address {
@@ -179,13 +192,6 @@ pub fn get_backstop_token(e: &Env) -> Address {
.unwrap_optimized()
}
-/// Checks if a backstop token is set for the backstop
-pub fn has_backstop_token(e: &Env) -> bool {
- e.storage()
- .instance()
- .has(&Symbol::new(e, BACKSTOP_TOKEN_KEY))
-}
-
/// Set the backstop token id
///
/// ### Arguments
diff --git a/emitter/src/contract.rs b/emitter/src/contract.rs
index 4dddc740..c8f65983 100644
--- a/emitter/src/contract.rs
+++ b/emitter/src/contract.rs
@@ -76,7 +76,7 @@ pub trait Emitter {
impl Emitter for EmitterContract {
fn initialize(e: Env, blnd_token: Address, backstop: Address, backstop_token: Address) {
storage::extend_instance(&e);
- if storage::has_blnd_token(&e) {
+ if storage::get_is_init(&e) {
panic_with_error!(&e, EmitterError::AlreadyInitialized)
}
@@ -84,6 +84,8 @@ impl Emitter for EmitterContract {
storage::set_backstop(&e, &backstop);
storage::set_backstop_token(&e, &backstop_token);
storage::set_last_distro_time(&e, &backstop, e.ledger().timestamp());
+
+ storage::set_is_init(&e);
}
fn distribute(e: Env) -> i128 {
diff --git a/emitter/src/storage.rs b/emitter/src/storage.rs
index 1f68bfa6..3111b2a2 100644
--- a/emitter/src/storage.rs
+++ b/emitter/src/storage.rs
@@ -7,6 +7,7 @@ pub(crate) const LEDGER_BUMP_SHARED: u32 = 241920; // ~ 14 days
/********** Storage **********/
+const IS_INIT_KEY: &str = "IsInit";
const BACKSTOP_KEY: &str = "Backstop";
const BACKSTOP_TOKEN_KEY: &str = "BToken";
const BLND_TOKEN_KEY: &str = "BLNDTkn";
@@ -30,6 +31,20 @@ pub fn extend_instance(e: &Env) {
.extend_ttl(LEDGER_THRESHOLD_SHARED, LEDGER_BUMP_SHARED);
}
+/********** Init **********/
+
+/// Check if the contract has been initialized
+pub fn get_is_init(e: &Env) -> bool {
+ e.storage().instance().has(&Symbol::new(e, IS_INIT_KEY))
+}
+
+/// Set the contract as initialized
+pub fn set_is_init(e: &Env) {
+ e.storage()
+ .instance()
+ .set::(&Symbol::new(e, IS_INIT_KEY), &true);
+}
+
/********** Backstop **********/
/// Fetch the current backstop address
@@ -128,13 +143,6 @@ pub fn set_blnd_token(e: &Env, blnd_token: &Address) {
.set::(&Symbol::new(e, BLND_TOKEN_KEY), blnd_token);
}
-/// Check if the BLND token has been set
-///
-/// Returns true if a BLND token has been set
-pub fn has_blnd_token(e: &Env) -> bool {
- e.storage().instance().has(&Symbol::new(e, BLND_TOKEN_KEY))
-}
-
/********** Blend Distributions **********/
/// Fetch the last timestamp distribution was ran on
diff --git a/pool-factory/src/pool_factory.rs b/pool-factory/src/pool_factory.rs
index 9ec846f5..b359aaaa 100644
--- a/pool-factory/src/pool_factory.rs
+++ b/pool-factory/src/pool_factory.rs
@@ -51,10 +51,13 @@ pub trait PoolFactory {
impl PoolFactory for PoolFactoryContract {
fn initialize(e: Env, pool_init_meta: PoolInitMeta) {
storage::extend_instance(&e);
- if storage::has_pool_init_meta(&e) {
+ if storage::get_is_init(&e) {
panic_with_error!(&e, PoolFactoryError::AlreadyInitialized);
}
+
storage::set_pool_init_meta(&e, &pool_init_meta);
+
+ storage::set_is_init(&e);
}
fn deploy(
diff --git a/pool-factory/src/storage.rs b/pool-factory/src/storage.rs
index ad726e96..8f7d2392 100644
--- a/pool-factory/src/storage.rs
+++ b/pool-factory/src/storage.rs
@@ -4,6 +4,8 @@ use soroban_sdk::{contracttype, unwrap::UnwrapOptimized, Address, BytesN, Env, S
pub(crate) const LEDGER_THRESHOLD: u32 = 518400; // TODO: Check on phase 1 max ledger entry bump
pub(crate) const LEDGER_BUMP: u32 = 535670; // TODO: Check on phase 1 max ledger entry bump
+const IS_INIT_KEY: &str = "IsInit";
+
#[derive(Clone)]
#[contracttype]
pub enum PoolFactoryDataKey {
@@ -26,6 +28,18 @@ pub fn extend_instance(e: &Env) {
.extend_ttl(LEDGER_THRESHOLD, LEDGER_BUMP);
}
+/// Check if the contract has been initialized
+pub fn get_is_init(e: &Env) -> bool {
+ e.storage().instance().has(&Symbol::new(e, IS_INIT_KEY))
+}
+
+/// Set the contract as initialized
+pub fn set_is_init(e: &Env) {
+ e.storage()
+ .instance()
+ .set::(&Symbol::new(e, IS_INIT_KEY), &true);
+}
+
/// Fetch the pool initialization metadata
pub fn get_pool_init_meta(e: &Env) -> PoolInitMeta {
e.storage()
@@ -44,11 +58,6 @@ pub fn set_pool_init_meta(e: &Env, pool_init_meta: &PoolInitMeta) {
.set::(&Symbol::new(e, "PoolMeta"), pool_init_meta)
}
-/// Check if the factory has a WASM hash set
-pub fn has_pool_init_meta(e: &Env) -> bool {
- e.storage().instance().has(&Symbol::new(e, "PoolMeta"))
-}
-
/// Check if a given contract_id was deployed by the factory
///
/// ### Arguments
diff --git a/pool/src/pool/config.rs b/pool/src/pool/config.rs
index c4efdc00..19a7f813 100644
--- a/pool/src/pool/config.rs
+++ b/pool/src/pool/config.rs
@@ -22,7 +22,7 @@ pub fn execute_initialize(
blnd_id: &Address,
usdc_id: &Address,
) {
- if storage::has_admin(e) {
+ if storage::get_is_init(e) {
panic_with_error!(e, PoolError::AlreadyInitialized);
}
@@ -45,6 +45,8 @@ pub fn execute_initialize(
);
storage::set_blnd_token(e, blnd_id);
storage::set_usdc_token(e, usdc_id);
+
+ storage::set_is_init(e);
}
/// Update the pool
@@ -184,7 +186,7 @@ mod tests {
let name = Symbol::new(&e, "pool_name");
let oracle = Address::generate(&e);
let bstop_rate = 0_100_000_000u64;
- let max_postions = 2;
+ let max_positions = 2;
let backstop_address = Address::generate(&e);
let blnd_id = Address::generate(&e);
let usdc_id = Address::generate(&e);
@@ -196,7 +198,7 @@ mod tests {
&name,
&oracle,
&bstop_rate,
- &max_postions,
+ &max_positions,
&backstop_address,
&blnd_id,
&usdc_id,
@@ -213,6 +215,90 @@ mod tests {
});
}
+ #[test]
+ #[should_panic(expected = "Error(Contract, #3)")]
+ fn test_execute_initialize_already_initialized() {
+ let e = Env::default();
+ let pool = testutils::create_pool(&e);
+
+ let admin = Address::generate(&e);
+ let name = Symbol::new(&e, "pool_name");
+ let oracle = Address::generate(&e);
+ let bstop_rate = 0_100_000_000u64;
+ let max_positions = 3;
+ let backstop_address = Address::generate(&e);
+ let blnd_id = Address::generate(&e);
+ let usdc_id = Address::generate(&e);
+
+ e.as_contract(&pool, || {
+ execute_initialize(
+ &e,
+ &admin,
+ &name,
+ &oracle,
+ &bstop_rate,
+ &max_positions,
+ &backstop_address,
+ &blnd_id,
+ &usdc_id,
+ );
+
+ execute_initialize(
+ &e,
+ &Address::generate(&e),
+ &name,
+ &oracle,
+ &bstop_rate,
+ &max_positions,
+ &backstop_address,
+ &blnd_id,
+ &usdc_id,
+ );
+ });
+ }
+
+ #[test]
+ #[should_panic(expected = "Error(Contract, #5)")]
+ fn test_execute_initialize_bad_take_rate() {
+ let e = Env::default();
+ let pool = testutils::create_pool(&e);
+
+ let admin = Address::generate(&e);
+ let name = Symbol::new(&e, "pool_name");
+ let oracle = Address::generate(&e);
+ let bstop_rate = 1_000_000_000u64;
+ let max_positions = 3;
+ let backstop_address = Address::generate(&e);
+ let blnd_id = Address::generate(&e);
+ let usdc_id = Address::generate(&e);
+
+ e.as_contract(&pool, || {
+ execute_initialize(
+ &e,
+ &admin,
+ &name,
+ &oracle,
+ &bstop_rate,
+ &max_positions,
+ &backstop_address,
+ &blnd_id,
+ &usdc_id,
+ );
+
+ execute_initialize(
+ &e,
+ &Address::generate(&e),
+ &name,
+ &oracle,
+ &bstop_rate,
+ &max_positions,
+ &backstop_address,
+ &blnd_id,
+ &usdc_id,
+ );
+ });
+ }
+
#[test]
fn test_execute_update_pool() {
let e = Env::default();
diff --git a/pool/src/storage.rs b/pool/src/storage.rs
index 44be2a5a..e8d7fd2f 100644
--- a/pool/src/storage.rs
+++ b/pool/src/storage.rs
@@ -95,6 +95,7 @@ pub struct UserEmissionData {
/********** Storage Key Types **********/
+const IS_INIT_KEY: &str = "IsInit";
const ADMIN_KEY: &str = "Admin";
const NAME_KEY: &str = "Name";
const BACKSTOP_KEY: &str = "Backstop";
@@ -169,6 +170,20 @@ fn get_persistent_default, V: TryFromVal>(
}
}
+/********** Init **********/
+
+/// Check if the contract has been initialized
+pub fn get_is_init(e: &Env) -> bool {
+ e.storage().instance().has(&Symbol::new(e, IS_INIT_KEY))
+}
+
+/// Set the contract as initialized
+pub fn set_is_init(e: &Env) {
+ e.storage()
+ .instance()
+ .set::(&Symbol::new(e, IS_INIT_KEY), &true);
+}
+
/********** User **********/
/// Fetch the user's positions or return an empty Positions struct
@@ -224,11 +239,6 @@ pub fn set_admin(e: &Env, new_admin: &Address) {
.set::(&Symbol::new(e, ADMIN_KEY), new_admin);
}
-/// Checks if an admin is set
-pub fn has_admin(e: &Env) -> bool {
- e.storage().instance().has(&Symbol::new(e, ADMIN_KEY))
-}
-
/********** Metadata **********/
/// Set a pool name