solana-program-library/binary-oracle-pair/program/tests/tests.rs

1124 lines
32 KiB
Rust

#![cfg(feature = "test-bpf")]
use borsh::de::BorshDeserialize;
use solana_program::{hash::Hash, program_pack::Pack, pubkey::Pubkey, system_instruction};
use solana_program_test::*;
use solana_sdk::{
account::Account,
signature::{Keypair, Signer},
transaction::Transaction,
transport::TransportError,
};
use spl_binary_oracle_pair::*;
pub fn program_test() -> ProgramTest {
ProgramTest::new(
"spl_binary_oracle_pair",
id(),
processor!(processor::Processor::process_instruction),
)
}
pub async fn create_token_account(
banks_client: &mut BanksClient,
payer: &Keypair,
recent_blockhash: &Hash,
account: &Keypair,
mint: &Pubkey,
owner: &Pubkey,
) -> Result<(), TransportError> {
let rent = banks_client.get_rent().await.unwrap();
let account_rent = rent.minimum_balance(spl_token::state::Account::LEN);
let mut transaction = Transaction::new_with_payer(
&[
system_instruction::create_account(
&payer.pubkey(),
&account.pubkey(),
account_rent,
spl_token::state::Account::LEN as u64,
&spl_token::id(),
),
spl_token::instruction::initialize_account(
&spl_token::id(),
&account.pubkey(),
mint,
owner,
)
.unwrap(),
],
Some(&payer.pubkey()),
);
transaction.sign(&[payer, account], *recent_blockhash);
banks_client.process_transaction(transaction).await?;
Ok(())
}
pub async fn mint_tokens_to(
banks_client: &mut BanksClient,
payer: &Keypair,
recent_blockhash: &Hash,
mint: &Pubkey,
destination: &Pubkey,
authority: &Keypair,
amount: u64,
) -> Result<(), TransportError> {
let mut transaction = Transaction::new_with_payer(
&[spl_token::instruction::mint_to(
&spl_token::id(),
mint,
destination,
&authority.pubkey(),
&[&authority.pubkey()],
amount,
)
.unwrap()],
Some(&payer.pubkey()),
);
transaction.sign(&[payer, authority], *recent_blockhash);
banks_client.process_transaction(transaction).await?;
Ok(())
}
pub async fn approve_delegate(
banks_client: &mut BanksClient,
payer: &Keypair,
recent_blockhash: &Hash,
source: &Pubkey,
delegate: &Pubkey,
source_owner: &Keypair,
amount: u64,
) -> Result<(), TransportError> {
let mut transaction = Transaction::new_with_payer(
&[spl_token::instruction::approve(
&spl_token::id(),
source,
delegate,
&source_owner.pubkey(),
&[&source_owner.pubkey()],
amount,
)
.unwrap()],
Some(&payer.pubkey()),
);
transaction.sign(&[payer, source_owner], *recent_blockhash);
banks_client.process_transaction(transaction).await?;
Ok(())
}
pub async fn make_decision(
program_context: &mut ProgramTestContext,
pool_account: &Pubkey,
decider: &Keypair,
decision: bool,
) -> Result<(), TransportError> {
let mut transaction = Transaction::new_with_payer(
&[instruction::decide(&id(), pool_account, &decider.pubkey(), decision).unwrap()],
Some(&program_context.payer.pubkey()),
);
transaction.sign(
&[&program_context.payer, decider],
program_context.last_blockhash,
);
program_context
.banks_client
.process_transaction(transaction)
.await?;
Ok(())
}
pub async fn make_withdraw(
program_context: &mut ProgramTestContext,
pool_account: &Pubkey,
authority: &Pubkey,
user_transfer_authority: &Pubkey,
pool_deposit_account: &Pubkey,
user_pass_account: &Pubkey,
user_fail_account: &Pubkey,
token_pass_mint: &Pubkey,
token_fail_mint: &Pubkey,
user_account: &Pubkey,
withdraw_amount: u64,
) -> Result<(), TransportError> {
let mut transaction = Transaction::new_with_payer(
&[instruction::withdraw(
&id(),
pool_account,
authority,
user_transfer_authority,
pool_deposit_account,
user_pass_account,
user_fail_account,
token_pass_mint,
token_fail_mint,
user_account,
&spl_token::id(),
withdraw_amount,
)
.unwrap()],
Some(&program_context.payer.pubkey()),
);
transaction.sign(&[&program_context.payer], program_context.last_blockhash);
program_context
.banks_client
.process_transaction(transaction)
.await
.unwrap();
Ok(())
}
pub async fn get_token_balance(banks_client: &mut BanksClient, token: &Pubkey) -> u64 {
let token_account = banks_client.get_account(*token).await.unwrap().unwrap();
let account_info: spl_token::state::Account =
spl_token::state::Account::unpack_from_slice(token_account.data.as_slice()).unwrap();
account_info.amount
}
pub struct TestPool {
pub pool_account: Keypair,
pub authority: Pubkey,
pub bump_seed: u8,
pub deposit_token_mint: Keypair,
pub deposit_token_mint_owner: Keypair,
pub pool_deposit_account: Keypair,
pub token_pass_mint: Keypair,
pub token_fail_mint: Keypair,
pub decider: Keypair,
pub mint_end_slot: u64,
pub decide_end_slot: u64,
}
impl TestPool {
pub fn new() -> Self {
let pool_account = Keypair::new();
let (authority, bump_seed) =
Pubkey::find_program_address(&[&pool_account.pubkey().to_bytes()[..32]], &id());
Self {
pool_account,
authority,
bump_seed,
deposit_token_mint: Keypair::new(),
deposit_token_mint_owner: Keypair::new(),
pool_deposit_account: Keypair::new(),
token_pass_mint: Keypair::new(),
token_fail_mint: Keypair::new(),
decider: Keypair::new(),
mint_end_slot: 2,
decide_end_slot: 2000,
}
}
pub async fn init_pool(
&self,
banks_client: &mut BanksClient,
payer: &Keypair,
recent_blockhash: &Hash,
) {
let rent = banks_client.get_rent().await.unwrap();
let pool_rent = rent.minimum_balance(state::Pool::LEN);
let mint_rent = rent.minimum_balance(spl_token::state::Mint::LEN);
let account_rent = rent.minimum_balance(spl_token::state::Account::LEN);
// create pool account
create_account(
banks_client,
payer,
recent_blockhash,
&self.pool_account,
pool_rent,
state::Pool::LEN as u64,
&id(),
)
.await
.unwrap();
// create mint of deposit token
create_mint(
banks_client,
payer,
recent_blockhash,
&self.deposit_token_mint,
mint_rent,
&self.deposit_token_mint_owner.pubkey(),
)
.await
.unwrap();
let init_args = instruction::InitArgs {
mint_end_slot: self.mint_end_slot,
decide_end_slot: self.decide_end_slot,
bump_seed: self.bump_seed,
};
let mut transaction = Transaction::new_with_payer(
&[
system_instruction::create_account(
&payer.pubkey(),
&self.pool_deposit_account.pubkey(),
account_rent,
spl_token::state::Account::LEN as u64,
&spl_token::id(),
),
system_instruction::create_account(
&payer.pubkey(),
&self.token_pass_mint.pubkey(),
mint_rent,
spl_token::state::Mint::LEN as u64,
&spl_token::id(),
),
system_instruction::create_account(
&payer.pubkey(),
&self.token_fail_mint.pubkey(),
mint_rent,
spl_token::state::Mint::LEN as u64,
&spl_token::id(),
),
instruction::init_pool(
&id(),
&self.pool_account.pubkey(),
&self.authority,
&self.decider.pubkey(),
&self.deposit_token_mint.pubkey(),
&self.pool_deposit_account.pubkey(),
&self.token_pass_mint.pubkey(),
&self.token_fail_mint.pubkey(),
&spl_token::id(),
init_args,
)
.unwrap(),
],
Some(&payer.pubkey()),
);
transaction.sign(
&[
payer,
&self.pool_deposit_account,
&self.token_pass_mint,
&self.token_fail_mint,
],
*recent_blockhash,
);
banks_client.process_transaction(transaction).await.unwrap();
}
#[allow(clippy::too_many_arguments)]
pub async fn prepare_accounts_for_deposit(
&self,
banks_client: &mut BanksClient,
payer: &Keypair,
recent_blockhash: &Hash,
deposit_tokens_to_mint: u64,
deposit_tokens_for_allowance: u64,
user_account: &Keypair,
authority: &Pubkey,
user_account_owner: &Keypair,
user_pass_account: &Keypair,
user_fail_account: &Keypair,
) {
// Create user account
create_token_account(
banks_client,
payer,
recent_blockhash,
user_account,
&self.deposit_token_mint.pubkey(),
&user_account_owner.pubkey(),
)
.await
.unwrap();
// Mint to him some deposit tokens
mint_tokens_to(
banks_client,
payer,
recent_blockhash,
&self.deposit_token_mint.pubkey(),
&user_account.pubkey(),
&self.deposit_token_mint_owner,
deposit_tokens_to_mint,
)
.await
.unwrap();
// Give allowance to pool authority
approve_delegate(
banks_client,
payer,
recent_blockhash,
&user_account.pubkey(),
authority,
user_account_owner,
deposit_tokens_for_allowance,
)
.await
.unwrap();
// Create token accounts for PASS and FAIL tokens
create_token_account(
banks_client,
payer,
recent_blockhash,
user_pass_account,
&self.token_pass_mint.pubkey(),
&user_account_owner.pubkey(),
)
.await
.unwrap();
create_token_account(
banks_client,
payer,
recent_blockhash,
user_fail_account,
&self.token_fail_mint.pubkey(),
&user_account_owner.pubkey(),
)
.await
.unwrap();
}
#[allow(clippy::too_many_arguments)]
pub async fn make_deposit(
&self,
banks_client: &mut BanksClient,
payer: &Keypair,
recent_blockhash: &Hash,
user_account: &Keypair,
user_pass_account: &Keypair,
user_fail_account: &Keypair,
deposit_amount: u64,
) {
let mut transaction = Transaction::new_with_payer(
&[instruction::deposit(
&id(),
&self.pool_account.pubkey(),
&self.authority,
&self.authority,
&user_account.pubkey(),
&self.pool_deposit_account.pubkey(),
&self.token_pass_mint.pubkey(),
&self.token_fail_mint.pubkey(),
&user_pass_account.pubkey(),
&user_fail_account.pubkey(),
&spl_token::id(),
deposit_amount,
)
.unwrap()],
Some(&payer.pubkey()),
);
transaction.sign(&[payer], *recent_blockhash);
banks_client.process_transaction(transaction).await.unwrap();
}
#[allow(clippy::too_many_arguments)]
pub async fn make_deposit_with_user_transfer_authority(
&self,
banks_client: &mut BanksClient,
payer: &Keypair,
recent_blockhash: &Hash,
user_account: &Keypair,
user_authority: &Keypair,
user_pass_account: &Keypair,
user_fail_account: &Keypair,
deposit_amount: u64,
) {
let mut transaction = Transaction::new_with_payer(
&[instruction::deposit(
&id(),
&self.pool_account.pubkey(),
&self.authority,
&user_authority.pubkey(),
&user_account.pubkey(),
&self.pool_deposit_account.pubkey(),
&self.token_pass_mint.pubkey(),
&self.token_fail_mint.pubkey(),
&user_pass_account.pubkey(),
&user_fail_account.pubkey(),
&spl_token::id(),
deposit_amount,
)
.unwrap()],
Some(&payer.pubkey()),
);
transaction.sign(&[payer, user_authority], *recent_blockhash);
banks_client.process_transaction(transaction).await.unwrap();
}
}
pub async fn create_mint(
banks_client: &mut BanksClient,
payer: &Keypair,
recent_blockhash: &Hash,
mint_account: &Keypair,
mint_rent: u64,
owner: &Pubkey,
) -> Result<(), TransportError> {
let mut transaction = Transaction::new_with_payer(
&[
system_instruction::create_account(
&payer.pubkey(),
&mint_account.pubkey(),
mint_rent,
spl_token::state::Mint::LEN as u64,
&spl_token::id(),
),
spl_token::instruction::initialize_mint(
&spl_token::id(),
&mint_account.pubkey(),
&owner,
None,
0,
)
.unwrap(),
],
Some(&payer.pubkey()),
);
transaction.sign(&[payer, mint_account], *recent_blockhash);
banks_client.process_transaction(transaction).await?;
Ok(())
}
pub async fn create_account(
banks_client: &mut BanksClient,
payer: &Keypair,
recent_blockhash: &Hash,
account: &Keypair,
rent: u64,
space: u64,
owner: &Pubkey,
) -> Result<(), TransportError> {
let mut transaction = Transaction::new_with_payer(
&[system_instruction::create_account(
&payer.pubkey(),
&account.pubkey(),
rent,
space,
owner,
)],
Some(&payer.pubkey()),
);
transaction.sign(&[payer, account], *recent_blockhash);
banks_client.process_transaction(transaction).await?;
Ok(())
}
async fn get_account(banks_client: &mut BanksClient, pubkey: &Pubkey) -> Account {
banks_client
.get_account(*pubkey)
.await
.expect("account not found")
.expect("account empty")
}
#[tokio::test]
async fn test_init_pool() {
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
let pool = TestPool::new();
pool.init_pool(&mut banks_client, &payer, &recent_blockhash)
.await;
let pool_account_data = get_account(&mut banks_client, &pool.pool_account.pubkey()).await;
assert_eq!(pool_account_data.data.len(), state::Pool::LEN);
assert_eq!(pool_account_data.owner, id());
// check if Pool is initialized
let pool = state::Pool::try_from_slice(pool_account_data.data.as_slice()).unwrap();
assert!(pool.is_initialized());
}
#[tokio::test]
async fn test_deposit_with_program_authority() {
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
let deposit_amount = 100;
let pool = TestPool::new();
pool.init_pool(&mut banks_client, &payer, &recent_blockhash)
.await;
let user_account = Keypair::new();
let user_account_owner = Keypair::new();
let user_pass_account = Keypair::new();
let user_fail_account = Keypair::new();
pool.prepare_accounts_for_deposit(
&mut banks_client,
&payer,
&recent_blockhash,
deposit_amount,
deposit_amount,
&user_account,
&pool.authority,
&user_account_owner,
&user_pass_account,
&user_fail_account,
)
.await;
let user_balance_before = get_token_balance(&mut banks_client, &user_account.pubkey()).await;
assert_eq!(user_balance_before, deposit_amount);
// Make deposit
pool.make_deposit(
&mut banks_client,
&payer,
&recent_blockhash,
&user_account,
&user_pass_account,
&user_fail_account,
deposit_amount,
)
.await;
// Check balance of user account
let user_balance_after = get_token_balance(&mut banks_client, &user_account.pubkey()).await;
assert_eq!(user_balance_after, 0);
// Check balance of pool deposit account
let pool_deposit_account_balance =
get_token_balance(&mut banks_client, &pool.pool_deposit_account.pubkey()).await;
assert_eq!(pool_deposit_account_balance, deposit_amount);
// Check if user has PASS and FAIL tokens
let user_pass_tokens = get_token_balance(&mut banks_client, &user_pass_account.pubkey()).await;
assert_eq!(user_pass_tokens, deposit_amount);
let user_fail_tokens = get_token_balance(&mut banks_client, &user_fail_account.pubkey()).await;
assert_eq!(user_fail_tokens, deposit_amount);
}
#[tokio::test]
async fn test_deposit_with_user_authority() {
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
let deposit_amount = 100;
let pool = TestPool::new();
pool.init_pool(&mut banks_client, &payer, &recent_blockhash)
.await;
let user_account = Keypair::new();
let user_account_owner = Keypair::new();
let user_transfer_authority = Keypair::new();
let user_pass_account = Keypair::new();
let user_fail_account = Keypair::new();
pool.prepare_accounts_for_deposit(
&mut banks_client,
&payer,
&recent_blockhash,
deposit_amount,
deposit_amount,
&user_account,
&user_transfer_authority.pubkey(),
&user_account_owner,
&user_pass_account,
&user_fail_account,
)
.await;
let user_balance_before = get_token_balance(&mut banks_client, &user_account.pubkey()).await;
assert_eq!(user_balance_before, deposit_amount);
// Make deposit
pool.make_deposit_with_user_transfer_authority(
&mut banks_client,
&payer,
&recent_blockhash,
&user_account,
&user_transfer_authority,
&user_pass_account,
&user_fail_account,
deposit_amount,
)
.await;
// Check balance of user account
let user_balance_after = get_token_balance(&mut banks_client, &user_account.pubkey()).await;
assert_eq!(user_balance_after, 0);
// Check balance of pool deposit account
let pool_deposit_account_balance =
get_token_balance(&mut banks_client, &pool.pool_deposit_account.pubkey()).await;
assert_eq!(pool_deposit_account_balance, deposit_amount);
// Check if user has PASS and FAIL tokens
let user_pass_tokens = get_token_balance(&mut banks_client, &user_pass_account.pubkey()).await;
assert_eq!(user_pass_tokens, deposit_amount);
let user_fail_tokens = get_token_balance(&mut banks_client, &user_fail_account.pubkey()).await;
assert_eq!(user_fail_tokens, deposit_amount);
}
#[tokio::test]
async fn test_withdraw_no_decision() {
let mut program_context = program_test().start_with_context().await;
let deposit_amount = 100;
let withdraw_amount = 50;
let pool = TestPool::new();
pool.init_pool(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
)
.await;
let user_account = Keypair::new();
let user_account_owner = Keypair::new();
let user_pass_account = Keypair::new();
let user_fail_account = Keypair::new();
pool.prepare_accounts_for_deposit(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
deposit_amount,
deposit_amount,
&user_account,
&pool.authority,
&user_account_owner,
&user_pass_account,
&user_fail_account,
)
.await;
// Make deposit
pool.make_deposit(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
&user_account,
&user_pass_account,
&user_fail_account,
deposit_amount,
)
.await;
// Set allowances to burn PASS and FAIL tokens
approve_delegate(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
&user_pass_account.pubkey(),
&pool.authority,
&user_account_owner,
deposit_amount,
)
.await
.unwrap();
approve_delegate(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
&user_fail_account.pubkey(),
&pool.authority,
&user_account_owner,
deposit_amount,
)
.await
.unwrap();
let user_balance_before =
get_token_balance(&mut program_context.banks_client, &user_account.pubkey()).await;
assert_eq!(user_balance_before, 0);
// Check balance of pool deposit account
let pool_deposit_account_balance = get_token_balance(
&mut program_context.banks_client,
&pool.pool_deposit_account.pubkey(),
)
.await;
assert_eq!(pool_deposit_account_balance, deposit_amount);
// Check if user has PASS and FAIL tokens
let user_pass_tokens = get_token_balance(
&mut program_context.banks_client,
&user_pass_account.pubkey(),
)
.await;
assert_eq!(user_pass_tokens, deposit_amount);
let user_fail_tokens = get_token_balance(
&mut program_context.banks_client,
&user_fail_account.pubkey(),
)
.await;
assert_eq!(user_fail_tokens, deposit_amount);
make_withdraw(
&mut program_context,
&pool.pool_account.pubkey(),
&pool.authority,
&pool.authority,
&pool.pool_deposit_account.pubkey(),
&user_pass_account.pubkey(),
&user_fail_account.pubkey(),
&pool.token_pass_mint.pubkey(),
&pool.token_fail_mint.pubkey(),
&user_account.pubkey(),
withdraw_amount,
)
.await
.unwrap();
let user_balance_after =
get_token_balance(&mut program_context.banks_client, &user_account.pubkey()).await;
assert_eq!(user_balance_after, withdraw_amount);
// Check balance of pool deposit account after withdraw
let pool_deposit_account_balance_after = get_token_balance(
&mut program_context.banks_client,
&pool.pool_deposit_account.pubkey(),
)
.await;
assert_eq!(
pool_deposit_account_balance_after,
deposit_amount - withdraw_amount
);
// Check if program burned PASS and FAIL tokens
let user_pass_tokens_after = get_token_balance(
&mut program_context.banks_client,
&user_pass_account.pubkey(),
)
.await;
assert_eq!(user_pass_tokens_after, deposit_amount - withdraw_amount);
let user_fail_tokens_after = get_token_balance(
&mut program_context.banks_client,
&user_fail_account.pubkey(),
)
.await;
assert_eq!(user_fail_tokens_after, deposit_amount - withdraw_amount);
}
#[tokio::test]
async fn test_withdraw_pass_decision() {
let mut program_context = program_test().start_with_context().await;
let deposit_amount = 100;
let withdraw_amount = 50;
let pool = TestPool::new();
pool.init_pool(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
)
.await;
let user_account = Keypair::new();
let user_account_owner = Keypair::new();
let user_pass_account = Keypair::new();
let user_fail_account = Keypair::new();
pool.prepare_accounts_for_deposit(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
deposit_amount,
deposit_amount,
&user_account,
&pool.authority,
&user_account_owner,
&user_pass_account,
&user_fail_account,
)
.await;
// Make deposit
pool.make_deposit(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
&user_account,
&user_pass_account,
&user_fail_account,
deposit_amount,
)
.await;
// Set allowances to burn PASS and FAIL tokens
approve_delegate(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
&user_pass_account.pubkey(),
&pool.authority,
&user_account_owner,
deposit_amount,
)
.await
.unwrap();
approve_delegate(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
&user_fail_account.pubkey(),
&pool.authority,
&user_account_owner,
deposit_amount,
)
.await
.unwrap();
let decision = true;
program_context
.warp_to_slot(pool.mint_end_slot + 1)
.unwrap();
make_decision(
&mut program_context,
&pool.pool_account.pubkey(),
&pool.decider,
decision,
)
.await
.unwrap();
make_withdraw(
&mut program_context,
&pool.pool_account.pubkey(),
&pool.authority,
&pool.authority,
&pool.pool_deposit_account.pubkey(),
&user_pass_account.pubkey(),
&user_fail_account.pubkey(),
&pool.token_pass_mint.pubkey(),
&pool.token_fail_mint.pubkey(),
&user_account.pubkey(),
withdraw_amount,
)
.await
.unwrap();
let user_balance_after =
get_token_balance(&mut program_context.banks_client, &user_account.pubkey()).await;
assert_eq!(user_balance_after, withdraw_amount);
// Check balance of pool deposit account after withdraw
let pool_deposit_account_balance_after = get_token_balance(
&mut program_context.banks_client,
&pool.pool_deposit_account.pubkey(),
)
.await;
assert_eq!(
pool_deposit_account_balance_after,
deposit_amount - withdraw_amount
);
// Check if program burned PASS and FAIL tokens
let user_pass_tokens_after = get_token_balance(
&mut program_context.banks_client,
&user_pass_account.pubkey(),
)
.await;
assert_eq!(user_pass_tokens_after, deposit_amount - withdraw_amount);
let user_fail_tokens_after = get_token_balance(
&mut program_context.banks_client,
&user_fail_account.pubkey(),
)
.await;
assert_eq!(user_fail_tokens_after, deposit_amount);
}
#[tokio::test]
async fn test_withdraw_fail_decision() {
let mut program_context = program_test().start_with_context().await;
let deposit_amount = 100;
let withdraw_amount = 50;
let pool = TestPool::new();
pool.init_pool(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
)
.await;
let user_account = Keypair::new();
let user_account_owner = Keypair::new();
let user_pass_account = Keypair::new();
let user_fail_account = Keypair::new();
pool.prepare_accounts_for_deposit(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
deposit_amount,
deposit_amount,
&user_account,
&pool.authority,
&user_account_owner,
&user_pass_account,
&user_fail_account,
)
.await;
// Make deposit
pool.make_deposit(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
&user_account,
&user_pass_account,
&user_fail_account,
deposit_amount,
)
.await;
// Set allowances to burn PASS and FAIL tokens
approve_delegate(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
&user_pass_account.pubkey(),
&pool.authority,
&user_account_owner,
deposit_amount,
)
.await
.unwrap();
approve_delegate(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
&user_fail_account.pubkey(),
&pool.authority,
&user_account_owner,
deposit_amount,
)
.await
.unwrap();
let decision = false;
program_context
.warp_to_slot(pool.mint_end_slot + 1)
.unwrap();
make_decision(
&mut program_context,
&pool.pool_account.pubkey(),
&pool.decider,
decision,
)
.await
.unwrap();
make_withdraw(
&mut program_context,
&pool.pool_account.pubkey(),
&pool.authority,
&pool.authority,
&pool.pool_deposit_account.pubkey(),
&user_pass_account.pubkey(),
&user_fail_account.pubkey(),
&pool.token_pass_mint.pubkey(),
&pool.token_fail_mint.pubkey(),
&user_account.pubkey(),
withdraw_amount,
)
.await
.unwrap();
let user_balance_after =
get_token_balance(&mut program_context.banks_client, &user_account.pubkey()).await;
assert_eq!(user_balance_after, withdraw_amount);
// Check balance of pool deposit account after withdraw
let pool_deposit_account_balance_after = get_token_balance(
&mut program_context.banks_client,
&pool.pool_deposit_account.pubkey(),
)
.await;
assert_eq!(
pool_deposit_account_balance_after,
deposit_amount - withdraw_amount
);
// Check if program burned PASS and FAIL tokens
let user_pass_tokens_after = get_token_balance(
&mut program_context.banks_client,
&user_pass_account.pubkey(),
)
.await;
assert_eq!(user_pass_tokens_after, deposit_amount);
let user_fail_tokens_after = get_token_balance(
&mut program_context.banks_client,
&user_fail_account.pubkey(),
)
.await;
assert_eq!(user_fail_tokens_after, deposit_amount - withdraw_amount);
}
#[tokio::test]
async fn test_decide() {
let mut program_context = program_test().start_with_context().await;
let pool = TestPool::new();
pool.init_pool(
&mut program_context.banks_client,
&program_context.payer,
&program_context.last_blockhash,
)
.await;
let pool_account_data_before = program_context
.banks_client
.get_account(pool.pool_account.pubkey())
.await
.unwrap()
.unwrap();
let pool_data_before =
state::Pool::try_from_slice(pool_account_data_before.data.as_slice()).unwrap();
assert_eq!(pool_data_before.decision, state::Decision::Undecided);
let decision = true;
program_context
.warp_to_slot(pool.mint_end_slot + 1)
.unwrap();
make_decision(
&mut program_context,
&pool.pool_account.pubkey(),
&pool.decider,
decision,
)
.await
.unwrap();
let pool_account_data_after = program_context
.banks_client
.get_account(pool.pool_account.pubkey())
.await
.unwrap()
.unwrap();
let pool_data_after =
state::Pool::try_from_slice(pool_account_data_after.data.as_slice()).unwrap();
assert_eq!(pool_data_after.decision, state::Decision::Pass);
}