test: add fallback oracle withdrawal test
This commit is contained in:
parent
d4017e6038
commit
20261bf734
|
@ -228,7 +228,7 @@ fn pyth_get_price(
|
|||
|
||||
/// Returns the price of one native base token, in native quote tokens
|
||||
///
|
||||
/// Example: The for SOL at 40 USDC/SOL it would return 0.04 (the unit is USDC-native/SOL-native)
|
||||
/// Example: The price for SOL at 40 USDC/SOL it would return 0.04 (the unit is USDC-native/SOL-native)
|
||||
///
|
||||
/// This currently assumes that quote decimals (i.e. decimals for USD) is 6, like for USDC.
|
||||
///
|
||||
|
|
|
@ -286,6 +286,7 @@ async fn test_basic() -> Result<(), TransportError> {
|
|||
send_tx(
|
||||
solana,
|
||||
StubOracleCloseInstruction {
|
||||
oracle: tokens[0].oracle,
|
||||
group,
|
||||
mint: bank_data.mint,
|
||||
admin,
|
||||
|
|
|
@ -68,7 +68,7 @@ async fn test_health_compute_tokens() -> Result<(), TransportError> {
|
|||
let avg_cu_increase = cu_measurements.windows(2).map(|p| p[1] - p[0]).sum::<u64>()
|
||||
/ (cu_measurements.len() - 1) as u64;
|
||||
println!("average cu increase: {avg_cu_increase}");
|
||||
assert!(avg_cu_increase < 3200);
|
||||
assert!(avg_cu_increase < 3230);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -244,7 +244,7 @@ async fn test_margin_trade() -> Result<(), BanksClientError> {
|
|||
#[tokio::test]
|
||||
async fn test_flash_loan_swap_fee() -> Result<(), BanksClientError> {
|
||||
let mut test_builder = TestContextBuilder::new();
|
||||
test_builder.test().set_compute_max_units(100_000);
|
||||
test_builder.test().set_compute_max_units(150_000);
|
||||
let context = test_builder.start_default().await;
|
||||
let solana = &context.solana.clone();
|
||||
|
||||
|
|
|
@ -975,7 +975,7 @@ async fn test_perp_pnl_settle_limit() -> Result<(), TransportError> {
|
|||
send_tx(
|
||||
solana,
|
||||
StubOracleSetInstruction {
|
||||
oracle: tokens[0].oracle,
|
||||
oracle: tokens[1].oracle,
|
||||
group,
|
||||
admin,
|
||||
mint: mints[1].pubkey,
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use super::*;
|
||||
use anchor_lang::prelude::AccountMeta;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_stale_oracle_deposit_withdraw() -> Result<(), TransportError> {
|
||||
let mut test_builder = TestContextBuilder::new();
|
||||
test_builder.test().set_compute_max_units(100_000); // bad oracles log a lot
|
||||
test_builder.test().set_compute_max_units(150_000); // bad oracles log a lot
|
||||
let context = test_builder.start_default().await;
|
||||
let solana = &context.solana.clone();
|
||||
|
||||
|
@ -174,3 +175,147 @@ async fn test_stale_oracle_deposit_withdraw() -> Result<(), TransportError> {
|
|||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_fallback_oracle_withdraw() -> Result<(), TransportError> {
|
||||
let mut test_builder = TestContextBuilder::new();
|
||||
test_builder.test().set_compute_max_units(150_000); // bad oracles log a lot
|
||||
let context = test_builder.start_default().await;
|
||||
let solana = &context.solana.clone();
|
||||
|
||||
let fallback_oracle_kp = TestKeypair::new();
|
||||
let fallback_oracle = fallback_oracle_kp.pubkey();
|
||||
let admin = TestKeypair::new();
|
||||
let owner = context.users[0].key;
|
||||
let payer = context.users[1].key;
|
||||
let mints = &context.mints[0..3];
|
||||
let payer_token_accounts = &context.users[1].token_accounts[0..3];
|
||||
|
||||
//
|
||||
// SETUP: Create a group, account, register tokens
|
||||
//Foracle_
|
||||
|
||||
let mango_setup::GroupWithTokens { group, tokens, .. } = mango_setup::GroupWithTokensConfig {
|
||||
admin,
|
||||
payer,
|
||||
mints: mints.to_vec(),
|
||||
..mango_setup::GroupWithTokensConfig::default()
|
||||
}
|
||||
.create(solana)
|
||||
.await;
|
||||
|
||||
// setup fallback_oracle
|
||||
send_tx(
|
||||
solana,
|
||||
StubOracleCreate {
|
||||
oracle: fallback_oracle_kp,
|
||||
group,
|
||||
mint: mints[2].pubkey,
|
||||
admin,
|
||||
payer,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// add a fallback oracle
|
||||
send_tx(
|
||||
solana,
|
||||
TokenEdit {
|
||||
group,
|
||||
admin,
|
||||
mint: mints[2].pubkey,
|
||||
options: mango_v4::instruction::TokenEdit {
|
||||
fallback_oracle_opt: Some(fallback_oracle),
|
||||
..token_edit_instruction_default()
|
||||
},
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let bank_data: Bank = solana.get_account(tokens[2].bank).await;
|
||||
assert!(bank_data.fallback_oracle == fallback_oracle);
|
||||
|
||||
// fill vaults, so we can borrow
|
||||
let _vault_account = create_funded_account(
|
||||
&solana,
|
||||
group,
|
||||
owner,
|
||||
2,
|
||||
&context.users[1],
|
||||
mints,
|
||||
100_000,
|
||||
0,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Create account with token3 of deposits
|
||||
let account = create_funded_account(
|
||||
&solana,
|
||||
group,
|
||||
owner,
|
||||
0,
|
||||
&context.users[1],
|
||||
&[mints[2]],
|
||||
1_000_000,
|
||||
0,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Create some token1 borrows
|
||||
send_tx(
|
||||
solana,
|
||||
TokenWithdrawInstruction {
|
||||
amount: 1,
|
||||
allow_borrow: true,
|
||||
account,
|
||||
owner,
|
||||
token_account: payer_token_accounts[1],
|
||||
bank_index: 0,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Make oracle invalid by increasing deviation
|
||||
send_tx(
|
||||
solana,
|
||||
StubOracleSetTestInstruction {
|
||||
oracle: tokens[2].oracle,
|
||||
group,
|
||||
mint: mints[2].pubkey,
|
||||
admin,
|
||||
price: 1.0,
|
||||
last_update_slot: 0,
|
||||
deviation: 100.0,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let token_withdraw_ix = TokenWithdrawInstruction {
|
||||
amount: 1,
|
||||
allow_borrow: true,
|
||||
account,
|
||||
owner,
|
||||
token_account: payer_token_accounts[2],
|
||||
bank_index: 0,
|
||||
};
|
||||
|
||||
// Verify that withdrawing collateral won't work
|
||||
assert!(send_tx(solana, token_withdraw_ix.clone(),).await.is_err());
|
||||
|
||||
// now send txn with a fallback oracle in the remaining accounts
|
||||
let fallback_oracle_meta = AccountMeta {
|
||||
pubkey: fallback_oracle,
|
||||
is_writable: false,
|
||||
is_signer: false,
|
||||
};
|
||||
send_tx_with_extra_accounts(solana, token_withdraw_ix, vec![fallback_oracle_meta])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ impl ClientAccountLoader for &SolanaCookie {
|
|||
}
|
||||
}
|
||||
|
||||
// This fill return a failure if the tx resulted in an error
|
||||
// This will return a failure if the tx resulted in an error
|
||||
pub async fn send_tx<CI: ClientInstruction>(
|
||||
solana: &SolanaCookie,
|
||||
ix: CI,
|
||||
|
@ -57,6 +57,23 @@ pub async fn send_tx<CI: ClientInstruction>(
|
|||
Ok(accounts)
|
||||
}
|
||||
|
||||
// This will return a failure if the tx resulted in an error
|
||||
pub async fn send_tx_with_extra_accounts<CI: ClientInstruction>(
|
||||
solana: &SolanaCookie,
|
||||
ix: CI,
|
||||
account_metas: Vec<AccountMeta>,
|
||||
) -> std::result::Result<CI::Accounts, TransportError> {
|
||||
let (accounts, mut instruction) = ix.to_instruction(solana).await;
|
||||
instruction.accounts.extend(account_metas);
|
||||
let signers = ix.signers();
|
||||
let instructions = vec![instruction.clone()];
|
||||
let result = solana
|
||||
.process_transaction(&instructions, Some(&signers[..]))
|
||||
.await?;
|
||||
result.result?;
|
||||
Ok(accounts)
|
||||
}
|
||||
|
||||
// This will return success even if the tx failed to finish
|
||||
pub async fn send_tx_get_metadata<CI: ClientInstruction>(
|
||||
solana: &SolanaCookie,
|
||||
|
@ -724,6 +741,7 @@ impl ClientInstruction for FlashLoanEndInstruction {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TokenWithdrawInstruction {
|
||||
pub amount: u64,
|
||||
pub allow_borrow: bool,
|
||||
|
@ -795,6 +813,7 @@ impl ClientInstruction for TokenWithdrawInstruction {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TokenDepositInstruction {
|
||||
pub amount: u64,
|
||||
pub reduce_only: bool,
|
||||
|
@ -1670,6 +1689,7 @@ impl ClientInstruction for StubOracleCreate {
|
|||
}
|
||||
|
||||
pub struct StubOracleCloseInstruction {
|
||||
pub oracle: Pubkey,
|
||||
pub group: Pubkey,
|
||||
pub mint: Pubkey,
|
||||
pub admin: TestKeypair,
|
||||
|
@ -1687,20 +1707,10 @@ impl ClientInstruction for StubOracleCloseInstruction {
|
|||
let program_id = mango_v4::id();
|
||||
let instruction = Self::Instruction {};
|
||||
|
||||
let oracle = Pubkey::find_program_address(
|
||||
&[
|
||||
b"StubOracle".as_ref(),
|
||||
self.group.as_ref(),
|
||||
self.mint.as_ref(),
|
||||
],
|
||||
&program_id,
|
||||
)
|
||||
.0;
|
||||
|
||||
let accounts = Self::Accounts {
|
||||
group: self.group,
|
||||
admin: self.admin.pubkey(),
|
||||
oracle,
|
||||
oracle: self.oracle,
|
||||
sol_destination: self.sol_destination,
|
||||
token_program: Token::id(),
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue