2024-02-14 02:32:57 -08:00
|
|
|
#![allow(unused_assignments)]
|
2024-02-13 03:39:28 -08:00
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
async fn test_collateral_fees() -> Result<(), TransportError> {
|
|
|
|
let context = TestContext::new().await;
|
|
|
|
let solana = &context.solana.clone();
|
|
|
|
|
|
|
|
let admin = TestKeypair::new();
|
|
|
|
let owner = context.users[0].key;
|
|
|
|
let payer = context.users[1].key;
|
|
|
|
let mints = &context.mints[0..2];
|
|
|
|
|
|
|
|
let mango_setup::GroupWithTokens { group, tokens, .. } = mango_setup::GroupWithTokensConfig {
|
|
|
|
admin,
|
|
|
|
payer,
|
|
|
|
mints: mints.to_vec(),
|
|
|
|
..mango_setup::GroupWithTokensConfig::default()
|
|
|
|
}
|
|
|
|
.create(solana)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
// fund the vaults to allow borrowing
|
|
|
|
create_funded_account(
|
|
|
|
&solana,
|
|
|
|
group,
|
|
|
|
owner,
|
|
|
|
0,
|
|
|
|
&context.users[1],
|
|
|
|
mints,
|
|
|
|
1_000_000,
|
|
|
|
0,
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
let account = create_funded_account(
|
|
|
|
&solana,
|
|
|
|
group,
|
|
|
|
owner,
|
|
|
|
1,
|
|
|
|
&context.users[1],
|
|
|
|
&mints[0..1],
|
|
|
|
1_500, // maint: 0.8 * 1500 = 1200
|
|
|
|
0,
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
|
2024-02-14 02:32:57 -08:00
|
|
|
let empty_account = create_funded_account(
|
|
|
|
&solana,
|
|
|
|
group,
|
|
|
|
owner,
|
|
|
|
2,
|
|
|
|
&context.users[1],
|
|
|
|
&mints[0..0],
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
|
2024-02-13 03:39:28 -08:00
|
|
|
let hour = 60 * 60;
|
|
|
|
|
|
|
|
send_tx(
|
|
|
|
solana,
|
|
|
|
GroupEdit {
|
|
|
|
group,
|
|
|
|
admin,
|
|
|
|
options: mango_v4::instruction::GroupEdit {
|
|
|
|
collateral_fee_interval_opt: Some(6 * hour),
|
|
|
|
..group_edit_instruction_default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
send_tx(
|
|
|
|
solana,
|
|
|
|
TokenEdit {
|
|
|
|
group,
|
|
|
|
admin,
|
|
|
|
mint: mints[0].pubkey,
|
|
|
|
fallback_oracle: Pubkey::default(),
|
|
|
|
options: mango_v4::instruction::TokenEdit {
|
|
|
|
collateral_fee_per_day_opt: Some(0.1),
|
|
|
|
..token_edit_instruction_default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
send_tx(
|
|
|
|
solana,
|
|
|
|
TokenEdit {
|
|
|
|
group,
|
|
|
|
admin,
|
|
|
|
mint: mints[1].pubkey,
|
|
|
|
fallback_oracle: Pubkey::default(),
|
|
|
|
options: mango_v4::instruction::TokenEdit {
|
|
|
|
loan_origination_fee_rate_opt: Some(0.0),
|
|
|
|
..token_edit_instruction_default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
2024-02-14 02:32:57 -08:00
|
|
|
//
|
|
|
|
// TEST: It works on empty accounts
|
|
|
|
//
|
|
|
|
|
|
|
|
send_tx(
|
|
|
|
solana,
|
|
|
|
TokenChargeCollateralFeesInstruction {
|
|
|
|
account: empty_account,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
let mut last_time = solana.clock_timestamp().await;
|
|
|
|
solana.set_clock_timestamp(last_time + 9 * hour).await;
|
|
|
|
|
|
|
|
// send it twice, because the first time will never charge anything
|
|
|
|
send_tx(
|
|
|
|
solana,
|
|
|
|
TokenChargeCollateralFeesInstruction {
|
|
|
|
account: empty_account,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
last_time = solana.clock_timestamp().await;
|
|
|
|
|
2024-02-13 03:39:28 -08:00
|
|
|
//
|
|
|
|
// TEST: Without borrows, charging collateral fees has no effect
|
|
|
|
//
|
|
|
|
|
|
|
|
send_tx(solana, TokenChargeCollateralFeesInstruction { account })
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2024-02-14 02:32:57 -08:00
|
|
|
last_time = solana.clock_timestamp().await;
|
|
|
|
solana.set_clock_timestamp(last_time + 9 * hour).await;
|
|
|
|
|
|
|
|
// send it twice, because the first time will never charge anything
|
|
|
|
send_tx(solana, TokenChargeCollateralFeesInstruction { account })
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
last_time = solana.clock_timestamp().await;
|
|
|
|
|
2024-02-13 03:39:28 -08:00
|
|
|
// no effect
|
|
|
|
assert_eq!(
|
|
|
|
account_position(solana, account, tokens[0].bank).await,
|
|
|
|
1_500
|
|
|
|
);
|
|
|
|
|
|
|
|
//
|
|
|
|
// TEST: With borrows, there's an effect depending on the time that has passed
|
|
|
|
//
|
|
|
|
|
|
|
|
send_tx(
|
|
|
|
solana,
|
|
|
|
TokenWithdrawInstruction {
|
|
|
|
amount: 500, // maint: -1.2 * 500 = -600 (half of 1200)
|
|
|
|
allow_borrow: true,
|
|
|
|
account,
|
|
|
|
owner,
|
|
|
|
token_account: context.users[1].token_accounts[1],
|
|
|
|
bank_index: 0,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
solana.set_clock_timestamp(last_time + 9 * hour).await;
|
|
|
|
|
|
|
|
send_tx(solana, TokenChargeCollateralFeesInstruction { account })
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
last_time = solana.clock_timestamp().await;
|
2024-02-27 06:56:03 -08:00
|
|
|
assert_eq_f64!(
|
2024-02-13 03:39:28 -08:00
|
|
|
account_position_f64(solana, account, tokens[0].bank).await,
|
|
|
|
1500.0 * (1.0 - 0.1 * (9.0 / 24.0) * (600.0 / 1200.0)),
|
|
|
|
0.01
|
2024-02-27 06:56:03 -08:00
|
|
|
);
|
2024-02-13 03:39:28 -08:00
|
|
|
let last_balance = account_position_f64(solana, account, tokens[0].bank).await;
|
|
|
|
|
|
|
|
//
|
|
|
|
// TEST: More borrows
|
|
|
|
//
|
|
|
|
|
|
|
|
send_tx(
|
|
|
|
solana,
|
|
|
|
TokenWithdrawInstruction {
|
|
|
|
amount: 100, // maint: -1.2 * 600 = -720
|
|
|
|
allow_borrow: true,
|
|
|
|
account,
|
|
|
|
owner,
|
|
|
|
token_account: context.users[1].token_accounts[1],
|
|
|
|
bank_index: 0,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
solana.set_clock_timestamp(last_time + 7 * hour).await;
|
|
|
|
|
|
|
|
send_tx(solana, TokenChargeCollateralFeesInstruction { account })
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
//last_time = solana.clock_timestamp().await;
|
2024-02-27 06:56:03 -08:00
|
|
|
assert_eq_f64!(
|
2024-02-13 03:39:28 -08:00
|
|
|
account_position_f64(solana, account, tokens[0].bank).await,
|
|
|
|
last_balance * (1.0 - 0.1 * (7.0 / 24.0) * (720.0 / (last_balance * 0.8))),
|
|
|
|
0.01
|
2024-02-27 06:56:03 -08:00
|
|
|
);
|
2024-02-13 03:39:28 -08:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|