Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: optimize health check for submit #223

Merged
merged 1 commit into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion pool/src/auctions/bad_debt_auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ pub fn fill_bad_debt_auction(
let backstop_client = BackstopClient::new(e, &backstop_address);
let backstop_token_id = backstop_client.backstop_token();
let lot_amount = auction_data.lot.get(backstop_token_id).unwrap_optimized();
let backstop_client = BackstopClient::new(e, &backstop_address);
backstop_client.draw(
&e.current_contract_address(),
&lot_amount,
Expand Down
88 changes: 88 additions & 0 deletions pool/src/pool/submit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub fn execute_submit(
// panics if the new positions set does not meet the health factor requirement
// min is 1.0000100 to prevent rounding errors
if check_health
&& new_from_state.has_liabilities()
&& PositionData::calculate_from_positions(e, &mut pool, &new_from_state.positions)
.is_hf_under(1_0000100)
{
Expand Down Expand Up @@ -173,6 +174,93 @@ mod tests {
});
}

#[test]
fn test_submit_no_liabilities_does_not_load_oracle() {
let e = Env::default();
e.budget().reset_unlimited();
e.mock_all_auths_allowing_non_root_auth();

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

let bombadil = Address::generate(&e);
let samwise = Address::generate(&e);
let frodo = Address::generate(&e);
let pool = testutils::create_pool(&e);
let oracle = Address::generate(&e); // will fail if executed against

let (underlying_0, underlying_0_client) = testutils::create_token_contract(&e, &bombadil);
let (reserve_config, reserve_data) = testutils::default_reserve_meta();
testutils::create_reserve(&e, &pool, &underlying_0, &reserve_config, &reserve_data);

let (underlying_1, underlying_1_client) = testutils::create_token_contract(&e, &bombadil);
let (reserve_config, reserve_data) = testutils::default_reserve_meta();
testutils::create_reserve(&e, &pool, &underlying_1, &reserve_config, &reserve_data);

underlying_0_client.mint(&frodo, &16_0000000);
underlying_1_client.mint(&frodo, &10_0000000);

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

let pre_pool_balance_0 = underlying_0_client.balance(&pool);
let pre_pool_balance_1 = underlying_1_client.balance(&pool);

let requests = vec![
&e,
Request {
request_type: RequestType::SupplyCollateral as u32,
address: underlying_0,
amount: 15_0000000,
},
// force check_health to true
Request {
request_type: RequestType::Borrow as u32,
address: underlying_1.clone(),
amount: 1_5000000,
},
Request {
request_type: RequestType::Repay as u32,
address: underlying_1,
amount: 1_5000001,
},
];
let positions = execute_submit(&e, &samwise, &frodo, &frodo, requests);

assert_eq!(positions.liabilities.len(), 0);
assert_eq!(positions.collateral.len(), 1);
assert_eq!(positions.supply.len(), 0);
assert_eq!(positions.collateral.get_unchecked(0), 14_9999884);

assert_eq!(
underlying_0_client.balance(&pool),
pre_pool_balance_0 + 15_0000000
);
assert_eq!(
underlying_1_client.balance(&pool),
pre_pool_balance_1 + 1 // repayment rounded against user
);

assert_eq!(underlying_0_client.balance(&frodo), 1_0000000);
assert_eq!(underlying_1_client.balance(&frodo), 10_0000000 - 1);
});
}

#[test]
#[should_panic(expected = "Error(Contract, #1205)")]
fn test_submit_requires_healhty() {
Expand Down
13 changes: 13 additions & 0 deletions pool/src/pool/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ impl User {
storage::set_user_positions(e, &self.address, &self.positions);
}

/// Check if the user has liabilities
pub fn has_liabilities(&self) -> bool {
!self.positions.liabilities.is_empty()
}

/// Get the debtToken position for the reserve at the given index
pub fn get_liabilities(&self, reserve_index: u32) -> i128 {
self.positions.liabilities.get(reserve_index).unwrap_or(0)
Expand Down Expand Up @@ -287,10 +292,12 @@ mod tests {
};
e.as_contract(&pool, || {
assert_eq!(user.get_liabilities(0), 0);
assert_eq!(user.has_liabilities(), false);

user.add_liabilities(&e, &mut reserve_0, 123);
assert_eq!(user.get_liabilities(0), 123);
assert_eq!(reserve_0.d_supply, starting_d_supply_0 + 123);
assert_eq!(user.has_liabilities(), true);

user.add_liabilities(&e, &mut reserve_1, 456);
assert_eq!(user.get_liabilities(0), 123);
Expand All @@ -305,6 +312,12 @@ mod tests {
assert_eq!(user.get_liabilities(1), 0);
assert_eq!(user.positions.liabilities.len(), 1);
assert_eq!(reserve_1.d_supply, starting_d_supply_1);

user.remove_liabilities(&e, &mut reserve_0, 123);
assert_eq!(user.get_liabilities(0), 0);
assert_eq!(user.positions.liabilities.len(), 0);
assert_eq!(reserve_0.d_supply, starting_d_supply_0);
assert_eq!(user.has_liabilities(), false);
});
}

Expand Down
Loading