Skip to content

Commit 96fac37

Browse files
committed
fix: block user liquidations when liabilities equal collateral
1 parent f0296cf commit 96fac37

File tree

1 file changed

+96
-1
lines changed

1 file changed

+96
-1
lines changed

pool/src/auctions/user_liquidation_auction.rs

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub fn create_user_liq_auction_data(
4747
let position_data = PositionData::calculate_from_positions(e, &mut pool, &user_state.positions);
4848

4949
// ensure the user has less collateral than liabilities
50-
if position_data.liability_base < position_data.collateral_base {
50+
if position_data.liability_base <= position_data.collateral_base {
5151
panic_with_error!(e, PoolError::InvalidLiquidation);
5252
}
5353

@@ -2413,6 +2413,101 @@ mod tests {
24132413
});
24142414
}
24152415

2416+
#[test]
2417+
#[should_panic(expected = "Error(Contract, #1211)")]
2418+
fn test_create_user_liquidation_requires_unhealthy_user() {
2419+
let e = Env::default();
2420+
e.cost_estimate().budget().reset_unlimited();
2421+
2422+
e.mock_all_auths();
2423+
e.ledger().set(LedgerInfo {
2424+
timestamp: 12345,
2425+
protocol_version: 22,
2426+
sequence_number: 50,
2427+
network_id: Default::default(),
2428+
base_reserve: 10,
2429+
min_temp_entry_ttl: 10,
2430+
min_persistent_entry_ttl: 10,
2431+
max_entry_ttl: 3110400,
2432+
});
2433+
2434+
let bombadil = Address::generate(&e);
2435+
let samwise = Address::generate(&e);
2436+
2437+
let pool_address = create_pool(&e);
2438+
let (oracle_address, oracle_client) = testutils::create_mock_oracle(&e);
2439+
let backstop_address = Address::generate(&e);
2440+
2441+
// setup reserves to make it simple to have collateral_base == liabilities_base
2442+
let (underlying_0, _) = testutils::create_token_contract(&e, &bombadil);
2443+
let (mut reserve_config_0, mut reserve_data_0) = testutils::default_reserve_meta();
2444+
reserve_config_0.c_factor = 1_0000000;
2445+
reserve_config_0.l_factor = 1_0000000;
2446+
reserve_data_0.last_time = 12345;
2447+
reserve_config_0.index = 0;
2448+
testutils::create_reserve(
2449+
&e,
2450+
&pool_address,
2451+
&underlying_0,
2452+
&reserve_config_0,
2453+
&reserve_data_0,
2454+
);
2455+
2456+
let (underlying_1, _) = testutils::create_token_contract(&e, &bombadil);
2457+
let (mut reserve_config_1, mut reserve_data_1) = testutils::default_reserve_meta();
2458+
reserve_config_1.c_factor = 1_0000000;
2459+
reserve_config_1.l_factor = 1_0000000;
2460+
reserve_data_1.last_time = 12345;
2461+
reserve_config_1.index = 1;
2462+
testutils::create_reserve(
2463+
&e,
2464+
&pool_address,
2465+
&underlying_1,
2466+
&reserve_config_1,
2467+
&reserve_data_1,
2468+
);
2469+
2470+
oracle_client.set_data(
2471+
&bombadil,
2472+
&Asset::Other(Symbol::new(&e, "USD")),
2473+
&vec![
2474+
&e,
2475+
Asset::Stellar(underlying_0.clone()),
2476+
Asset::Stellar(underlying_1.clone()),
2477+
],
2478+
&7,
2479+
&300,
2480+
);
2481+
oracle_client.set_price_stable(&vec![&e, 2_0000000, 4_0000000]);
2482+
2483+
let liq_pct = 45;
2484+
let positions: Positions = Positions {
2485+
collateral: map![&e, (0, 10_0000000),],
2486+
liabilities: map![&e, (1, 5_0000000),],
2487+
supply: map![&e],
2488+
};
2489+
let pool_config = PoolConfig {
2490+
oracle: oracle_address,
2491+
min_collateral: 1_0000000,
2492+
bstop_rate: 0_1000000,
2493+
status: 0,
2494+
max_positions: 4,
2495+
};
2496+
e.as_contract(&pool_address, || {
2497+
storage::set_user_positions(&e, &samwise, &positions);
2498+
storage::set_pool_config(&e, &pool_config);
2499+
storage::set_backstop(&e, &backstop_address);
2500+
2501+
create_user_liq_auction_data(
2502+
&e,
2503+
&samwise,
2504+
&vec![&e, underlying_1.clone()],
2505+
&vec![&e, underlying_0.clone()],
2506+
liq_pct,
2507+
);
2508+
});
2509+
}
2510+
24162511
#[test]
24172512
fn test_fill_user_liquidation_auction() {
24182513
let e = Env::default();

0 commit comments

Comments
 (0)