Skip to content

Commit

Permalink
Merge pull request #180 from blend-capital/reserve-cache
Browse files Browse the repository at this point in the history
pool: chore: make reserve caching system more obvious to use
  • Loading branch information
mootz12 authored Jan 4, 2024
2 parents a0ec8f1 + 8a454ab commit cd8e248
Show file tree
Hide file tree
Showing 21 changed files with 343 additions and 168 deletions.
4 changes: 3 additions & 1 deletion backstop/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ impl Backstop for BackstopContract {
drop_list: Map<Address, i128>,
) {
storage::extend_instance(&e);
if storage::has_backstop_token(&e) {
if storage::get_is_init(&e) {
panic_with_error!(e, BackstopError::AlreadyInitialized);
}

Expand All @@ -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 **********/
Expand Down
22 changes: 14 additions & 8 deletions backstop/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -97,7 +98,19 @@ fn get_persistent_default<K: IntoVal<Env, Val>, V: TryFromVal<Env, Val>>(
}
}

/********** 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, bool>(&Symbol::new(e, IS_INIT_KEY), &true);
}

/// Fetch the pool factory id
pub fn get_emitter(e: &Env) -> Address {
Expand Down Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion emitter/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,16 @@ 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)
}

storage::set_blnd_token(&e, &blnd_token);
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 {
Expand Down
22 changes: 15 additions & 7 deletions emitter/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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, bool>(&Symbol::new(e, IS_INIT_KEY), &true);
}

/********** Backstop **********/

/// Fetch the current backstop address
Expand Down Expand Up @@ -128,13 +143,6 @@ pub fn set_blnd_token(e: &Env, blnd_token: &Address) {
.set::<Symbol, Address>(&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
Expand Down
5 changes: 4 additions & 1 deletion pool-factory/src/pool_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
19 changes: 14 additions & 5 deletions pool-factory/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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, bool>(&Symbol::new(e, IS_INIT_KEY), &true);
}

/// Fetch the pool initialization metadata
pub fn get_pool_init_meta(e: &Env) -> PoolInitMeta {
e.storage()
Expand All @@ -44,11 +58,6 @@ pub fn set_pool_init_meta(e: &Env, pool_init_meta: &PoolInitMeta) {
.set::<Symbol, PoolInitMeta>(&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
Expand Down
16 changes: 7 additions & 9 deletions pool/src/auctions/auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,10 @@ mod tests {

let (underlying_0, _) = testutils::create_token_contract(&e, &bombadil);
let (mut reserve_config_0, mut reserve_data_0) = testutils::default_reserve_meta();
reserve_data_0.b_rate = 1_100_000_000;
reserve_data_0.last_time = 12345;
reserve_data_0.backstop_credit = 100_0000000;
reserve_data_0.b_supply = 1000_0000000;
reserve_data_0.d_supply = 750_0000000;
reserve_config_0.index = 0;
testutils::create_reserve(
&e,
Expand All @@ -448,8 +450,10 @@ mod tests {

let (underlying_1, _) = testutils::create_token_contract(&e, &bombadil);
let (mut reserve_config_1, mut reserve_data_1) = testutils::default_reserve_meta();
reserve_data_1.b_rate = 1_100_000_000;
reserve_data_1.last_time = 12345;
reserve_data_1.backstop_credit = 25_0000000;
reserve_data_1.b_supply = 250_0000000;
reserve_data_1.d_supply = 187_5000000;
reserve_config_1.index = 1;
testutils::create_reserve(
&e,
Expand Down Expand Up @@ -495,13 +499,7 @@ mod tests {
};
e.as_contract(&pool_address, || {
storage::set_pool_config(&e, &pool_config);
let pool = Pool::load(&e);
let mut reserve_0 = pool.load_reserve(&e, &underlying_0);
reserve_0.backstop_credit += 100_0000000;
reserve_0.store(&e);
let mut reserve_1 = pool.load_reserve(&e, &underlying_1);
reserve_1.backstop_credit += 25_0000000;
reserve_1.store(&e);

create(&e, 2);
assert!(storage::has_auction(&e, &2, &backstop_address));
});
Expand Down
60 changes: 23 additions & 37 deletions pool/src/auctions/backstop_interest_auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub fn create_interest_auction_data(e: &Env, backstop: &Address) -> AuctionData
for i in 0..reserve_list.len() {
let res_asset_address = reserve_list.get_unchecked(i);
// don't store updated reserve data back to ledger. This will occur on the the auction's fill.
let reserve = pool.load_reserve(e, &res_asset_address);
let reserve = pool.load_reserve(e, &res_asset_address, false);
if reserve.backstop_credit > 0 {
let asset_to_base = pool.load_price(e, &res_asset_address);
interest_value += i128(asset_to_base)
Expand Down Expand Up @@ -78,9 +78,9 @@ pub fn fill_interest_auction(

// lot contains underlying tokens, but the backstop credit must be updated on the reserve
for (res_asset_address, lot_amount) in auction_data.lot.iter() {
let mut reserve = pool.load_reserve(e, &res_asset_address);
let mut reserve = pool.load_reserve(e, &res_asset_address, true);
reserve.backstop_credit -= lot_amount;
pool.cache_reserve(reserve, true);
pool.cache_reserve(reserve);
TokenClient::new(e, &res_asset_address).transfer(
&e.current_contract_address(),
filler,
Expand Down Expand Up @@ -178,6 +178,7 @@ mod tests {
let (mut reserve_config_0, mut reserve_data_0) = testutils::default_reserve_meta();
reserve_data_0.b_rate = 1_100_000_000;
reserve_data_0.last_time = 12345;
reserve_data_0.backstop_credit = 10_0000000;
reserve_config_0.index = 0;
testutils::create_reserve(
&e,
Expand All @@ -191,6 +192,7 @@ mod tests {
let (mut reserve_config_1, mut reserve_data_1) = testutils::default_reserve_meta();
reserve_data_1.b_rate = 1_100_000_000;
reserve_data_1.last_time = 12345;
reserve_data_1.backstop_credit = 2_5000000;
reserve_config_1.index = 1;
testutils::create_reserve(
&e,
Expand Down Expand Up @@ -236,15 +238,8 @@ mod tests {
};
e.as_contract(&pool_address, || {
storage::set_pool_config(&e, &pool_config);
let pool = Pool::load(&e);
let mut reserve_0 = pool.load_reserve(&e, &underlying_0);
reserve_0.backstop_credit += 10_0000000;
reserve_0.store(&e);
let mut reserve_1 = pool.load_reserve(&e, &underlying_1);
reserve_1.backstop_credit += 2_5000000;
reserve_1.store(&e);
let result = create_interest_auction_data(&e, &backstop_address);

let result = create_interest_auction_data(&e, &backstop_address);
assert_eq!(result.block, 51);
assert_eq!(result.bid.get_unchecked(usdc_id), 42_0000000);
assert_eq!(result.bid.len(), 1);
Expand Down Expand Up @@ -288,8 +283,10 @@ mod tests {

let (underlying_0, _) = testutils::create_token_contract(&e, &bombadil);
let (mut reserve_config_0, mut reserve_data_0) = testutils::default_reserve_meta();
reserve_data_0.b_rate = 1_100_000_000;
reserve_data_0.last_time = 12345;
reserve_data_0.backstop_credit = 100_0000000;
reserve_data_0.b_supply = 1000_0000000;
reserve_data_0.d_supply = 750_0000000;
reserve_config_0.index = 0;
testutils::create_reserve(
&e,
Expand All @@ -301,8 +298,10 @@ mod tests {

let (underlying_1, _) = testutils::create_token_contract(&e, &bombadil);
let (mut reserve_config_1, mut reserve_data_1) = testutils::default_reserve_meta();
reserve_data_1.b_rate = 1_100_000_000;
reserve_data_1.last_time = 12345;
reserve_data_1.backstop_credit = 25_0000000;
reserve_data_1.b_supply = 250_0000000;
reserve_data_1.d_supply = 187_5000000;
reserve_config_1.index = 1;
testutils::create_reserve(
&e,
Expand All @@ -314,7 +313,6 @@ mod tests {

let (underlying_2, _) = testutils::create_token_contract(&e, &bombadil);
let (mut reserve_config_2, mut reserve_data_2) = testutils::default_reserve_meta();
reserve_data_2.b_rate = 1_100_000_000;
reserve_data_2.last_time = 12345;
reserve_config_2.index = 1;
testutils::create_reserve(
Expand Down Expand Up @@ -348,15 +346,8 @@ mod tests {
};
e.as_contract(&pool_address, || {
storage::set_pool_config(&e, &pool_config);
let pool = Pool::load(&e);
let mut reserve_0 = pool.load_reserve(&e, &underlying_0);
reserve_0.backstop_credit += 100_0000000;
reserve_0.store(&e);
let mut reserve_1 = pool.load_reserve(&e, &underlying_1);
reserve_1.backstop_credit += 25_0000000;
reserve_1.store(&e);
let result = create_interest_auction_data(&e, &backstop_address);

let result = create_interest_auction_data(&e, &backstop_address);
assert_eq!(result.block, 51);
assert_eq!(result.bid.get_unchecked(usdc_id), 420_0000000);
assert_eq!(result.bid.len(), 1);
Expand Down Expand Up @@ -400,8 +391,10 @@ mod tests {

let (underlying_0, _) = testutils::create_token_contract(&e, &bombadil);
let (mut reserve_config_0, mut reserve_data_0) = testutils::default_reserve_meta();
reserve_data_0.b_rate = 1_100_000_000;
reserve_data_0.last_time = 11845;
reserve_data_0.backstop_credit = 100_0000000;
reserve_data_0.b_supply = 1000_0000000;
reserve_data_0.d_supply = 750_0000000;
reserve_config_0.index = 0;
testutils::create_reserve(
&e,
Expand All @@ -413,8 +406,10 @@ mod tests {

let (underlying_1, _) = testutils::create_token_contract(&e, &bombadil);
let (mut reserve_config_1, mut reserve_data_1) = testutils::default_reserve_meta();
reserve_data_1.b_rate = 1_100_000_000;
reserve_data_1.last_time = 11845;
reserve_data_1.backstop_credit = 25_0000000;
reserve_data_1.b_supply = 250_0000000;
reserve_data_1.d_supply = 187_5000000;
reserve_config_1.index = 1;
testutils::create_reserve(
&e,
Expand All @@ -426,7 +421,6 @@ mod tests {

let (underlying_2, _) = testutils::create_token_contract(&e, &bombadil);
let (mut reserve_config_2, mut reserve_data_2) = testutils::default_reserve_meta();
reserve_data_2.b_rate = 1_100_000_000;
reserve_data_2.last_time = 11845;
reserve_config_2.index = 2;
testutils::create_reserve(
Expand Down Expand Up @@ -461,21 +455,13 @@ mod tests {
e.as_contract(&pool_address, || {
storage::set_pool_config(&e, &pool_config);

let pool = Pool::load(&e);
let mut reserve_0 = pool.load_reserve(&e, &underlying_0);
reserve_0.backstop_credit += 100_0000000;
reserve_0.store(&e);
let mut reserve_1 = pool.load_reserve(&e, &underlying_1);
reserve_1.backstop_credit += 25_0000000;
reserve_1.store(&e);

let result = create_interest_auction_data(&e, &backstop_address);
assert_eq!(result.block, 151);
assert_eq!(result.bid.get_unchecked(usdc_id), 420_0009794);
assert_eq!(result.bid.get_unchecked(usdc_id), 420_0012936);
assert_eq!(result.bid.len(), 1);
assert_eq!(result.lot.get_unchecked(underlying_0), 100_0000066);
assert_eq!(result.lot.get_unchecked(underlying_1), 25_0000066);
assert_eq!(result.lot.get_unchecked(underlying_2), 66);
assert_eq!(result.lot.get_unchecked(underlying_0), 100_0000714);
assert_eq!(result.lot.get_unchecked(underlying_1), 25_0000178);
assert_eq!(result.lot.get_unchecked(underlying_2), 71);
assert_eq!(result.lot.len(), 3);
});
}
Expand Down
2 changes: 1 addition & 1 deletion pool/src/auctions/bad_debt_auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub fn create_bad_debt_auction_data(e: &Env, backstop: &Address) -> AuctionData
for (reserve_index, liability_balance) in backstop_positions.liabilities.iter() {
let res_asset_address = reserve_list.get_unchecked(reserve_index);
if liability_balance > 0 {
let reserve = pool.load_reserve(e, &res_asset_address);
let reserve = pool.load_reserve(e, &res_asset_address, false);
let asset_to_base = pool.load_price(e, &res_asset_address);
let asset_balance = reserve.to_asset_from_d_token(liability_balance);
debt_value += i128(asset_to_base)
Expand Down
1 change: 1 addition & 0 deletions pool/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub enum PoolError {
InvalidPoolStatus = 11,
InvalidUtilRate = 12,
MaxPositionsExceeded = 13,
InternalReserveNotFound = 14,
// Emission Errors (20-29)
EmissionFailure = 20,
// Oracle Errors (30-39)
Expand Down
Loading

0 comments on commit cd8e248

Please sign in to comment.