Skip to content

Commit

Permalink
Merge pull request #216 from blend-capital/rm_usdc_oracle_dependancy
Browse files Browse the repository at this point in the history
Rm usdc oracle dependancy
  • Loading branch information
mootz12 authored Mar 27, 2024
2 parents 60be9d2 + 08180ad commit fe2f7eb
Show file tree
Hide file tree
Showing 6 changed files with 279 additions and 17 deletions.
5 changes: 1 addition & 4 deletions pool/src/auctions/auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,7 @@ pub fn delete_liquidation(e: &Env, user: &Address) {
storage::del_auction(e, &(AuctionType::UserLiquidation as u32), user);
}

/// Fills the auction from the invoker. The filler is expected to maintain allowances to both
/// the pool and the backstop module.
///
/// TODO: Use auth-next to avoid required allowances
/// Fills the auction from the invoker.
///
/// ### Arguments
/// * `pool` - The pool
Expand Down
136 changes: 131 additions & 5 deletions pool/src/auctions/backstop_interest_auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub fn create_interest_auction_data(
}

let mut pool = Pool::load(e);
let oracle_scalar = 10i128.pow(pool.load_price_decimals(e));
let mut auction_data = AuctionData {
lot: map![e],
bid: map![e],
Expand Down Expand Up @@ -48,13 +49,15 @@ pub fn create_interest_auction_data(
panic_with_error!(e, PoolError::BadRequest);
}

let usdc_token = storage::get_usdc_token(e);
let usdc_to_base = pool.load_price(e, &usdc_token);
let backstop_client = BackstopClient::new(&e, &storage::get_backstop(e));
let pool_backstop_data = backstop_client.pool_data(&e.current_contract_address());
let backstop_token_value_base = (pool_backstop_data.usdc * 5)
.fixed_div_floor(pool_backstop_data.tokens, usdc_to_base)
.unwrap_optimized();
let backstop_token_value_base = (pool_backstop_data
.usdc
.fixed_mul_floor(oracle_scalar, SCALAR_7)
.unwrap_optimized()
* 5)
.fixed_div_floor(pool_backstop_data.tokens, SCALAR_7)
.unwrap_optimized();
let bid_amount = interest_value
.fixed_mul_floor(1_4000000, SCALAR_7)
.unwrap_optimized()
Expand Down Expand Up @@ -396,6 +399,129 @@ mod tests {
});
}

#[test]
fn test_create_interest_auction_14_decimal_oracle() {
let e = Env::default();
e.mock_all_auths();
e.budget().reset_unlimited(); // setup exhausts budget

e.ledger().set(LedgerInfo {
timestamp: 12345,
protocol_version: 20,
sequence_number: 50,
network_id: Default::default(),
base_reserve: 10,
min_temp_entry_ttl: 10,
min_persistent_entry_ttl: 10,
max_entry_ttl: 2000000,
});

let bombadil = Address::generate(&e);

let pool_address = create_pool(&e);
let (usdc_id, _) = testutils::create_usdc_token(&e, &pool_address, &bombadil);
let (blnd_id, _) = testutils::create_blnd_token(&e, &pool_address, &bombadil);

let (backstop_token_id, _) = create_comet_lp_pool(&e, &bombadil, &blnd_id, &usdc_id);
let (backstop_address, backstop_client) = testutils::create_backstop(&e);
testutils::setup_backstop(
&e,
&pool_address,
&backstop_address,
&backstop_token_id,
&usdc_id,
&blnd_id,
);
backstop_client.deposit(&bombadil, &pool_address, &(50 * SCALAR_7));
backstop_client.update_tkn_val();
let (oracle_id, oracle_client) = testutils::create_mock_oracle(&e);

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.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,
&pool_address,
&underlying_0,
&reserve_config_0,
&reserve_data_0,
);

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.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,
&pool_address,
&underlying_1,
&reserve_config_1,
&reserve_data_1,
);

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.last_time = 12345;
reserve_config_2.index = 1;
testutils::create_reserve(
&e,
&pool_address,
&underlying_2,
&reserve_config_2,
&reserve_data_2,
);

oracle_client.set_data(
&bombadil,
&Asset::Other(Symbol::new(&e, "USD")),
&vec![
&e,
Asset::Stellar(underlying_0.clone()),
Asset::Stellar(underlying_1.clone()),
Asset::Stellar(underlying_2),
Asset::Stellar(usdc_id.clone()),
],
&14,
&300,
);
oracle_client.set_price_stable(&vec![
&e,
2_0000000_0000000,
4_0000000_0000000,
100_0000000_0000000,
1_0000000_0000000,
]);

let pool_config = PoolConfig {
oracle: oracle_id,
bstop_rate: 0_1000000,
status: 0,
max_positions: 4,
};
e.as_contract(&pool_address, || {
storage::set_pool_config(&e, &pool_config);

let result = create_interest_auction_data(
&e,
&backstop_address,
&vec![&e, underlying_0.clone(), underlying_1.clone()],
);
assert_eq!(result.block, 51);
assert_eq!(result.bid.get_unchecked(backstop_token_id), 336_0000000);
assert_eq!(result.bid.len(), 1);
assert_eq!(result.lot.get_unchecked(underlying_0), 100_0000000);
assert_eq!(result.lot.get_unchecked(underlying_1), 25_0000000);
assert_eq!(result.lot.len(), 2);
});
}

#[test]
fn test_create_interest_auction_applies_interest() {
let e = Env::default();
Expand Down
150 changes: 145 additions & 5 deletions pool/src/auctions/bad_debt_auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub fn create_bad_debt_auction_data(e: &Env, backstop: &Address) -> AuctionData
};

let mut pool = Pool::load(e);
let oracle_scalar = 10i128.pow(pool.load_price_decimals(e));
let backstop_positions = storage::get_user_positions(e, backstop);
let reserve_list = storage::get_res_list(e);
let mut debt_value = 0;
Expand All @@ -47,11 +48,10 @@ pub fn create_bad_debt_auction_data(e: &Env, backstop: &Address) -> AuctionData
// TODO: Remove backstop_token getter call if WASM cache is not implemented
let backstop_token = backstop_client.backstop_token();
let pool_backstop_data = backstop_client.pool_data(&e.current_contract_address());
let usdc_token = storage::get_usdc_token(e);
let usdc_to_base = pool.load_price(e, &usdc_token);
let backstop_value_base = usdc_to_base
.fixed_mul_floor(pool_backstop_data.usdc, SCALAR_7)
.unwrap_optimized()
let backstop_value_base = pool_backstop_data
.usdc
.fixed_mul_floor(oracle_scalar, SCALAR_7)
.unwrap_optimized() // adjust for oracle scalar
* 5; // Since the backstop LP token is an 80/20 split of USDC/BLND, we multiply by 5 to get the value of the BLND portion
let backstop_token_to_base = backstop_value_base
.fixed_div_floor(pool_backstop_data.tokens, SCALAR_7)
Expand Down Expand Up @@ -338,6 +338,146 @@ mod tests {
});
}

#[test]
fn test_create_bad_debt_auction_oracle_14_decimals() {
let e = Env::default();
e.mock_all_auths_allowing_non_root_auth();
e.budget().reset_unlimited(); // setup exhausts budget

e.ledger().set(LedgerInfo {
timestamp: 12345,
protocol_version: 20,
sequence_number: 50,
network_id: Default::default(),
base_reserve: 10,
min_temp_entry_ttl: 10,
min_persistent_entry_ttl: 10,
max_entry_ttl: 2000000,
});

let bombadil = Address::generate(&e);
let samwise = Address::generate(&e);
let pool_address = create_pool(&e);

let (blnd, blnd_client) = testutils::create_blnd_token(&e, &pool_address, &bombadil);
let (usdc, usdc_client) = testutils::create_usdc_token(&e, &pool_address, &bombadil);
let (lp_token, lp_token_client) =
testutils::create_comet_lp_pool(&e, &bombadil, &blnd, &usdc);
let (backstop_address, backstop_client) = testutils::create_backstop(&e);
testutils::setup_backstop(
&e,
&pool_address,
&backstop_address,
&lp_token,
&usdc,
&blnd,
);
// mint lp tokens
blnd_client.mint(&samwise, &500_001_0000000);
blnd_client.approve(&samwise, &lp_token, &i128::MAX, &99999);
usdc_client.mint(&samwise, &12_501_0000000);
usdc_client.approve(&samwise, &lp_token, &i128::MAX, &99999);
lp_token_client.join_pool(
&50_000_0000000,
&vec![&e, 500_001_0000000, 12_501_0000000],
&samwise,
);
backstop_client.deposit(&samwise, &pool_address, &50_000_0000000);
backstop_client.update_tkn_val();

let (oracle_id, oracle_client) = testutils::create_mock_oracle(&e);

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.d_rate = 1_100_000_000;
reserve_data_0.last_time = 12345;
reserve_config_0.index = 0;
testutils::create_reserve(
&e,
&pool_address,
&underlying_0,
&reserve_config_0,
&reserve_data_0,
);

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.d_rate = 1_200_000_000;
reserve_data_1.last_time = 12345;
reserve_config_1.index = 1;
testutils::create_reserve(
&e,
&pool_address,
&underlying_1,
&reserve_config_1,
&reserve_data_1,
);

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(
&e,
&pool_address,
&underlying_2,
&reserve_config_2,
&reserve_data_2,
);

oracle_client.set_data(
&bombadil,
&Asset::Other(Symbol::new(&e, "USD")),
&vec![
&e,
Asset::Stellar(underlying_0.clone()),
Asset::Stellar(underlying_1.clone()),
Asset::Stellar(underlying_2),
Asset::Stellar(usdc),
],
&14,
&300,
);
oracle_client.set_price_stable(&vec![
&e,
2_0000000_0000000,
4_0000000_0000000,
100_0000000_0000000,
1_0000000_0000000,
]);

let positions: Positions = Positions {
collateral: map![&e],
liabilities: map![
&e,
(reserve_config_0.index, 10_0000000),
(reserve_config_1.index, 2_5000000)
],
supply: map![&e],
};

let pool_config = PoolConfig {
oracle: oracle_id,
bstop_rate: 0_1000000,
status: 0,
max_positions: 4,
};
e.as_contract(&pool_address, || {
storage::set_pool_config(&e, &pool_config);
storage::set_user_positions(&e, &backstop_address, &positions);

let result = create_bad_debt_auction_data(&e, &backstop_address);

assert_eq!(result.block, 51);
assert_eq!(result.bid.get_unchecked(underlying_0), 10_0000000);
assert_eq!(result.bid.get_unchecked(underlying_1), 2_5000000);
assert_eq!(result.bid.len(), 2);
assert_eq!(result.lot.get_unchecked(lp_token), 38_0800000);
assert_eq!(result.lot.len(), 1);
});
}

#[test]
fn test_create_bad_debt_auction_max_balance() {
let e = Env::default();
Expand Down
1 change: 0 additions & 1 deletion pool/src/auctions/user_liquidation_auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::{errors::PoolError, storage};

use super::AuctionType;

// TODO: Revalidate math with alternative decimal reserve
pub fn create_user_liq_auction_data(
e: &Env,
user: &Address,
Expand Down
2 changes: 1 addition & 1 deletion test-suites/src/test_fixture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl TestFixture<'_> {
let (blnd_id, blnd_client) = create_stellar_token(&e, &bombadil);
let (eth_id, eth_client) = create_token(&e, &bombadil, 9, "wETH");
let (usdc_id, usdc_client) = create_stellar_token(&e, &bombadil);
let (xlm_id, xlm_client) = create_stellar_token(&e, &bombadil); // TODO: make native
let (xlm_id, xlm_client) = create_stellar_token(&e, &bombadil);
let (stable_id, stable_client) = create_token(&e, &bombadil, 6, "STABLE");

// deploy Blend Protocol contracts
Expand Down
2 changes: 1 addition & 1 deletion test-suites/tests/test_liquidation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ fn test_liquidations() {
frodo_stable_balance - usdc_bid_amount
+ stable_interest_lot_amount
.fixed_div_floor(2 * 10i128.pow(6), 10i128.pow(6))
.unwrap(), // - usdc_donate_bid_amount TODO: add donate diff when donating is implemented
.unwrap(),
10i128.pow(6),
);
assert_approx_eq_abs(
Expand Down

0 comments on commit fe2f7eb

Please sign in to comment.