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 6a90e49d..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
@@ -161,7 +163,7 @@ fn require_valid_reserve_metadata(e: &Env, metadata: &ReserveConfig) {
|| metadata.util > 0_9500000
|| (metadata.max_util > SCALAR_7_U32 || metadata.max_util <= metadata.util)
|| (metadata.r_one > metadata.r_two || metadata.r_two > metadata.r_three)
- || (metadata.reactivity > 0_0005000)
+ || (metadata.reactivity > 0_0001000)
{
panic_with_error!(e, PoolError::InvalidReserveMetadata);
}
@@ -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();
@@ -887,7 +973,7 @@ mod tests {
r_one: 0_0500000,
r_two: 0_5000000,
r_three: 1_5000000,
- reactivity: 5001,
+ reactivity: 0_0001001,
};
require_valid_reserve_metadata(&e, &metadata);
}
diff --git a/pool/src/pool/interest.rs b/pool/src/pool/interest.rs
index 33a52a4a..e770c30b 100644
--- a/pool/src/pool/interest.rs
+++ b/pool/src/pool/interest.rs
@@ -78,7 +78,7 @@ pub fn calc_accrual(
.fixed_mul_floor(util_dif_scaled, SCALAR_9)
.unwrap_optimized();
let rate_dif = util_error
- .fixed_mul_floor(i128(config.reactivity), SCALAR_9)
+ .fixed_mul_floor(i128(config.reactivity), SCALAR_7)
.unwrap_optimized();
let next_ir_mod = ir_mod + rate_dif;
let ir_mod_max = 10 * SCALAR_9;
@@ -93,7 +93,7 @@ pub fn calc_accrual(
.fixed_mul_ceil(util_dif_scaled, SCALAR_9)
.unwrap_optimized();
let rate_dif = util_error
- .fixed_mul_ceil(i128(config.reactivity), SCALAR_9)
+ .fixed_mul_ceil(i128(config.reactivity), SCALAR_7)
.unwrap_optimized();
let next_ir_mod = ir_mod + rate_dif;
let ir_mod_min = SCALAR_9 / 10;
@@ -133,7 +133,7 @@ mod tests {
r_one: 0_0500000,
r_two: 0_5000000,
r_three: 1_5000000,
- reactivity: 0_000_002_000,
+ reactivity: 0_0000020,
index: 0,
};
let ir_mod: i128 = 1_000_000_000;
@@ -168,7 +168,7 @@ mod tests {
r_one: 0_0500000,
r_two: 0_5000000,
r_three: 1_5000000,
- reactivity: 0_000_002_000,
+ reactivity: 0_0000020,
index: 0,
};
let ir_mod: i128 = 1_000_000_000;
@@ -203,7 +203,7 @@ mod tests {
r_one: 0_0500000,
r_two: 0_5000000,
r_three: 1_5000000,
- reactivity: 0_000_002_000,
+ reactivity: 0_0000020,
index: 0,
};
let ir_mod: i128 = 1_000_000_000;
@@ -238,7 +238,7 @@ mod tests {
r_one: 0_0500000,
r_two: 0_5000000,
r_three: 1_5000000,
- reactivity: 0_000_002_000,
+ reactivity: 0_0000020,
index: 0,
};
let ir_mod: i128 = 9_997_000_000;
@@ -272,7 +272,7 @@ mod tests {
r_one: 0_0500000,
r_two: 0_5000000,
r_three: 1_5000000,
- reactivity: 0_000_002_000,
+ reactivity: 0_0000020,
index: 0,
};
let ir_mod: i128 = 0_150_000_000;
@@ -306,7 +306,7 @@ mod tests {
r_one: 0_0500000,
r_two: 0_5000000,
r_three: 1_5000000,
- reactivity: 0_000_002_000,
+ reactivity: 0_0000020,
index: 0,
};
let ir_mod: i128 = 0_100_000_000;
diff --git a/pool/src/pool/reserve.rs b/pool/src/pool/reserve.rs
index 01553293..0887b2ac 100644
--- a/pool/src/pool/reserve.rs
+++ b/pool/src/pool/reserve.rs
@@ -20,10 +20,10 @@ pub struct Reserve {
pub c_factor: u32, // the collateral factor for the reserve
pub max_util: u32, // the maximum utilization rate for the reserve
pub last_time: u64, // the last block the data was updated
- pub scalar: i128, // scalar used for balances
+ pub scalar: i128, // scalar used for positions, b/d token supply, and credit
pub d_rate: i128, // the conversion rate from dToken to underlying (9 decimals)
pub b_rate: i128, // the conversion rate from bToken to underlying (9 decimals)
- pub ir_mod: i128, // the interest rate curve modifier
+ pub ir_mod: i128, // the interest rate curve modifier (9 decimals)
pub b_supply: i128, // the total supply of b tokens
pub d_supply: i128, // the total supply of d tokens
pub backstop_credit: i128, // the total amount of underlying tokens owed to the backstop
diff --git a/pool/src/storage.rs b/pool/src/storage.rs
index b3bceb4f..e8d7fd2f 100644
--- a/pool/src/storage.rs
+++ b/pool/src/storage.rs
@@ -44,8 +44,9 @@ pub struct ReserveConfig {
pub r_one: u32, // the R1 value in the interest rate formula scaled expressed in 7 decimals
pub r_two: u32, // the R2 value in the interest rate formula scaled expressed in 7 decimals
pub r_three: u32, // the R3 value in the interest rate formula scaled expressed in 7 decimals
- pub reactivity: u32, // the reactivity constant for the reserve scaled expressed in 9 decimals
+ pub reactivity: u32, // the reactivity constant for the reserve scaled expressed in 7 decimals
}
+
#[derive(Clone)]
#[contracttype]
pub struct QueuedReserveInit {
@@ -94,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";
@@ -168,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
@@ -223,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
diff --git a/pool/src/testutils.rs b/pool/src/testutils.rs
index a5007ba5..48240298 100644
--- a/pool/src/testutils.rs
+++ b/pool/src/testutils.rs
@@ -210,7 +210,7 @@ pub(crate) fn default_reserve_meta() -> (ReserveConfig, ReserveData) {
r_one: 0_0500000,
r_two: 0_5000000,
r_three: 1_5000000,
- reactivity: 0_000_002_000, // 10e-5
+ reactivity: 0_0000020, // 2e-6
index: 0,
},
ReserveData {
diff --git a/test-suites/src/pool.rs b/test-suites/src/pool.rs
index ed029dde..98e46096 100644
--- a/test-suites/src/pool.rs
+++ b/test-suites/src/pool.rs
@@ -15,7 +15,7 @@ pub fn default_reserve_metadata() -> ReserveConfig {
r_one: 0_0500000,
r_two: 0_5000000,
r_three: 1_5000000,
- reactivity: 0_000_002_000, // 10e-5
+ reactivity: 0_0000020, // 2e-6
index: 0,
}
}