Skip to content

Commit

Permalink
Pool: Added reserve init queues
Browse files Browse the repository at this point in the history
  • Loading branch information
markuspluna committed Dec 13, 2023
1 parent 9de293c commit 5d58cd4
Show file tree
Hide file tree
Showing 12 changed files with 326 additions and 24 deletions.
2 changes: 1 addition & 1 deletion emitter/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub fn set_queued_swap(e: &Env, swap: &Swap) {
);
}

/// Fetch the current queued backstop swap, or None
/// Delete the current queued backstop swap
pub fn del_queued_swap(e: &Env) {
e.storage().persistent().remove(&Symbol::new(e, SWAP_KEY));
}
Expand Down
5 changes: 4 additions & 1 deletion pool-factory/src/pool_factory.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
errors::PoolFactoryError,
storage::{self, PoolInitMeta},
storage::{self, PoolInitMeta, ReserveConfig},
};
use soroban_sdk::{
contract, contractclient, contractimpl, panic_with_error, vec, Address, BytesN, Env, IntoVal,
Expand Down Expand Up @@ -32,6 +32,7 @@ pub trait PoolFactory {
salt: BytesN<32>,
oracle: Address,
backstop_take_rate: u64,
reserves: Vec<(Address, ReserveConfig)>,
) -> Address;

/// Checks if contract address was deployed by the factory
Expand Down Expand Up @@ -60,6 +61,7 @@ impl PoolFactory for PoolFactoryContract {
salt: BytesN<32>,
oracle: Address,
backstop_take_rate: u64,
reserves: Vec<(Address, ReserveConfig)>,
) -> Address {
admin.require_auth();
storage::extend_instance(&e);
Expand All @@ -78,6 +80,7 @@ impl PoolFactory for PoolFactoryContract {
init_args.push_back(pool_init_meta.backstop.to_val());
init_args.push_back(pool_init_meta.blnd_id.to_val());
init_args.push_back(pool_init_meta.usdc_id.to_val());
init_args.push_back(reserves.to_val());
let pool_address = e
.deployer()
.with_current_contract(salt)
Expand Down
18 changes: 18 additions & 0 deletions pool-factory/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@ 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

/// The configuration information about a reserve asset
/// TODO: Duplicated from pool/storage.rs. Can this be moved to a common location?
#[derive(Clone)]
#[contracttype]
pub struct ReserveConfig {
pub index: u32, // the index of the reserve in the list
pub decimals: u32, // the decimals used in both the bToken and underlying contract
pub c_factor: u32, // the collateral factor for the reserve scaled expressed in 7 decimals
pub l_factor: u32, // the liability factor for the reserve scaled expressed in 7 decimals
pub util: u32, // the target utilization rate scaled expressed in 7 decimals
pub max_util: u32, // the maximum allowed utilization rate scaled expressed in 7 decimals
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
}


#[derive(Clone)]
#[contracttype]
pub enum PoolFactoryDataKey {
Expand Down
54 changes: 49 additions & 5 deletions pool-factory/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use soroban_sdk::{
vec, Address, BytesN, Env, IntoVal, Symbol,
};

use crate::{PoolFactoryClient, PoolFactoryContract, PoolInitMeta};
use crate::{
storage::ReserveConfig, test::pool::PoolDataKey, PoolFactoryClient, PoolFactoryContract,
PoolInitMeta,
};

mod pool {
soroban_sdk::contractimport!(file = "../target/wasm32-unknown-unknown/optimized/pool.wasm");
Expand Down Expand Up @@ -48,8 +51,27 @@ fn test_pool_factory() {
let name1 = Symbol::new(&e, "pool1");
let name2 = Symbol::new(&e, "pool2");
let salt = BytesN::<32>::random(&e);
let deployed_pool_address_1 =
pool_factory_client.deploy(&bombadil, &name1, &salt, &oracle, &backstop_rate);
let asset_id_0 = Address::generate(&e);
let metadata = ReserveConfig {
index: 0,
decimals: 7,
c_factor: 0_7500000,
l_factor: 0_7500000,
util: 0_5000000,
max_util: 0_9500000,
r_one: 0_0500000,
r_two: 0_5000000,
r_three: 1_5000000,
reactivity: 100,
};
let deployed_pool_address_1 = pool_factory_client.deploy(
&bombadil,
&name1,
&salt,
&oracle,
&backstop_rate,
&vec![&e, (asset_id_0.clone(), metadata.clone())],
);

let event = vec![&e, e.events().all().last_unchecked()];
assert_eq!(
Expand All @@ -65,8 +87,14 @@ fn test_pool_factory() {
);

let salt = BytesN::<32>::random(&e);
let deployed_pool_address_2 =
pool_factory_client.deploy(&bombadil, &name2, &salt, &oracle, &backstop_rate);
let deployed_pool_address_2 = pool_factory_client.deploy(
&bombadil,
&name2,
&salt,
&oracle,
&backstop_rate,
&vec![&e, (asset_id_0.clone(), metadata.clone())],
);

e.as_contract(&deployed_pool_address_1, || {
assert_eq!(
Expand Down Expand Up @@ -108,6 +136,22 @@ fn test_pool_factory() {
.unwrap(),
usdc_id.clone()
);
let key = PoolDataKey::ResConfig(asset_id_0.clone());
let set_config = e
.storage()
.persistent()
.get::<_, ReserveConfig>(&key)
.unwrap();
assert_eq!(set_config.decimals, metadata.decimals);
assert_eq!(set_config.c_factor, metadata.c_factor);
assert_eq!(set_config.l_factor, metadata.l_factor);
assert_eq!(set_config.util, metadata.util);
assert_eq!(set_config.max_util, metadata.max_util);
assert_eq!(set_config.r_one, metadata.r_one);
assert_eq!(set_config.r_two, metadata.r_two);
assert_eq!(set_config.r_three, metadata.r_three);
assert_eq!(set_config.reactivity, metadata.reactivity);
assert_eq!(set_config.index, 0);
});
assert_ne!(deployed_pool_address_1, deployed_pool_address_2);
assert!(pool_factory_client.is_pool(&deployed_pool_address_1));
Expand Down
3 changes: 3 additions & 0 deletions pool/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ pub const SCALAR_7: i128 = 1_0000000;

// seconds per year
pub const SECONDS_PER_YEAR: i128 = 31536000;

// approximate week in blocks assuming 5 seconds per block
pub const WEEK_IN_BLOCKS: u32 = 120960;
62 changes: 55 additions & 7 deletions pool/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::{
auctions::{self, AuctionData},
constants::WEEK_IN_BLOCKS,
emissions::{self, ReserveEmissionMetadata},
pool::{self, Positions, Request},
storage::{self, ReserveConfig},
storage::{self, QueuedReserveInit, ReserveConfig},
};
use soroban_sdk::{contract, contractclient, contractimpl, Address, Env, Symbol, Vec};

Expand Down Expand Up @@ -37,6 +38,7 @@ pub trait Pool {
backstop_id: Address,
blnd_id: Address,
usdc_id: Address,
reserves: Vec<(Address, ReserveConfig)>,
);

/// (Admin only) Set a new address as the admin of this pool
Expand All @@ -57,15 +59,35 @@ pub trait Pool {
/// If the caller is not the admin
fn update_pool(e: Env, backstop_take_rate: u64);

/// (Admin only) Initialize a reserve in the pool
/// (Admin only) Queues the initialization of a reserve in the pool
///
/// ### Arguments
/// * `asset` - The underlying asset to add as a reserve
/// * `config` - The ReserveConfig for the reserve
///
/// ### Panics
/// If the caller is not the admin or the reserve is already setup
fn init_reserve(e: Env, asset: Address, metadata: ReserveConfig) -> u32;
/// If the caller is not the admin
fn queue_init_reserve(e: Env, asset: Address, metadata: ReserveConfig);

/// (Admin only) Cancels the queued initialization of a reserve in the pool
///
/// ### Arguments
/// * `asset` - The underlying asset to add as a reserve
///
/// ### Panics
/// If the caller is not the admin or the reserve is not queued for initialization
fn cancel_init_reserve(e: Env, asset: Address);

/// (Admin only) Executes the queued initialization of a reserve in the pool
///
/// ### Arguments
/// * `asset` - The underlying asset to add as a reserve
///
/// ### Panics
/// If the reserve is not queued for initialization
/// or is already setup
/// or has invalid metadata
fn init_reserve(e: Env, asset: Address) -> u32;

/// (Admin only) Update a reserve in the pool
///
Expand Down Expand Up @@ -224,6 +246,7 @@ impl Pool for PoolContract {
backstop_id: Address,
blnd_id: Address,
usdc_id: Address,
reserves: Vec<(Address, ReserveConfig)>,
) {
storage::extend_instance(&e);

Expand All @@ -236,6 +259,7 @@ impl Pool for PoolContract {
&backstop_id,
&blnd_id,
&usdc_id,
&reserves,
);
}

Expand All @@ -261,15 +285,39 @@ impl Pool for PoolContract {
.publish((Symbol::new(&e, "update_pool"), admin), backstop_take_rate);
}

fn init_reserve(e: Env, asset: Address, config: ReserveConfig) -> u32 {
fn queue_init_reserve(e: Env, asset: Address, metadata: ReserveConfig) {
storage::extend_instance(&e);
let admin = storage::get_admin(&e);
admin.require_auth();

let index = pool::initialize_reserve(&e, &asset, &config);
storage::set_queued_reserve_init(
&e,
&QueuedReserveInit {
new_config: metadata.clone(),
unlock_block: e.ledger().sequence() + WEEK_IN_BLOCKS,
},
&asset,
);

e.events().publish(
(Symbol::new(&e, "queue_init_reserve"), admin),
(asset, metadata),
);
}

fn cancel_init_reserve(e: Env, asset: Address) {
storage::extend_instance(&e);
let admin = storage::get_admin(&e);
admin.require_auth();

storage::del_queued_reserve_init(&e, &asset);

e.events()
.publish((Symbol::new(&e, "init_reserve"), admin), (asset, index));
.publish((Symbol::new(&e, "cancel_init_reserve"), admin), asset);
}

fn init_reserve(e: Env, asset: Address) -> u32 {
let index = pool::execute_queued_reserve_initialization(&e, &asset);
index
}

Expand Down
1 change: 1 addition & 0 deletions pool/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub enum PoolError {
NegativeAmount = 4,
InvalidPoolInitArgs = 5,
InvalidReserveMetadata = 6,
InitNotUnlocked = 7,
// Pool State Errors (10-19)
InvalidHf = 10,
InvalidPoolStatus = 11,
Expand Down
Loading

0 comments on commit 5d58cd4

Please sign in to comment.