RegisterToken: Pass token_index explicitly

This guarantees stability when a gov proposal adds a new token and a new
market in one transaction. This way the RegisterMarket instruction knows
exactly what index the new token will have.

Previously, the new token index was generated automatically, meaning
you couldn't be sure what index a new token would get in advance.
This commit is contained in:
Christian Kamm 2022-03-14 13:19:50 +01:00
parent 2502f0ac1b
commit 1cd0f8d6be
13 changed files with 118 additions and 75 deletions

View File

@ -19,7 +19,8 @@ pub struct Deposit<'info> {
mut, mut,
has_one = group, has_one = group,
has_one = vault, has_one = vault,
constraint = bank.load()?.mint == token_account.mint, // the mints of bank/vault/token_account are implicitly the same because
// spl::token::transfer succeeds between token_account and vault
)] )]
pub bank: AccountLoader<'info, Bank>, pub bank: AccountLoader<'info, Bank>,
@ -49,10 +50,7 @@ impl<'info> Deposit<'info> {
// That would save a lot of computation that needs to go into finding the // That would save a lot of computation that needs to go into finding the
// right index for the mint. // right index for the mint.
pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> { pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> {
// Find the mint's token index let token_index = ctx.accounts.bank.load()?.token_index as usize;
let group = ctx.accounts.group.load()?;
let mint = ctx.accounts.token_account.mint;
let token_index = group.tokens.index_for_mint(&mint)?;
// Get the account's position for that token index // Get the account's position for that token index
let mut account = ctx.accounts.account.load_mut()?; let mut account = ctx.accounts.account.load_mut()?;

View File

@ -2,6 +2,7 @@ use anchor_lang::prelude::*;
use anchor_spl::dex; use anchor_spl::dex;
use anchor_spl::token::{Token, TokenAccount}; use anchor_spl::token::{Token, TokenAccount};
use dex::serum_dex; use dex::serum_dex;
use serum_dex::matching::Side;
use crate::error::*; use crate::error::*;
use crate::state::*; use crate::state::*;
@ -49,7 +50,8 @@ pub struct PlaceSerumOrder<'info> {
#[account(mut)] #[account(mut)]
pub market_quote_vault: UncheckedAccount<'info>, pub market_quote_vault: UncheckedAccount<'info>,
// TODO: everything // TODO: everything; do we need to pass both, or just payer?
// these are all potentially mut too, if we settle immediately?
pub quote_bank: AccountLoader<'info, Bank>, pub quote_bank: AccountLoader<'info, Bank>,
pub quote_vault: Account<'info, TokenAccount>, pub quote_vault: Account<'info, TokenAccount>,
pub base_bank: AccountLoader<'info, Bank>, pub base_bank: AccountLoader<'info, Bank>,
@ -63,6 +65,11 @@ pub fn place_serum_order(
ctx: Context<PlaceSerumOrder>, ctx: Context<PlaceSerumOrder>,
order: serum_dex::instruction::NewOrderInstructionV3, order: serum_dex::instruction::NewOrderInstructionV3,
) -> Result<()> { ) -> Result<()> {
let order_payer_token_account = match order.side {
Side::Ask => ctx.accounts.base_vault.to_account_info(),
Side::Bid => ctx.accounts.quote_vault.to_account_info(),
};
let context = CpiContext::new( let context = CpiContext::new(
ctx.accounts.serum_program.to_account_info(), ctx.accounts.serum_program.to_account_info(),
dex::NewOrderV3 { dex::NewOrderV3 {
@ -80,8 +87,7 @@ pub fn place_serum_order(
// user accounts // user accounts
open_orders: ctx.accounts.open_orders.to_account_info(), open_orders: ctx.accounts.open_orders.to_account_info(),
open_orders_authority: ctx.accounts.serum_market.to_account_info(), open_orders_authority: ctx.accounts.serum_market.to_account_info(),
// TODO: vary based on bid or ask order_payer_token_account,
order_payer_token_account: ctx.accounts.quote_vault.to_account_info(),
}, },
); );

View File

@ -12,6 +12,7 @@ use crate::state::*;
const INDEX_START: I80F48 = I80F48!(1_000_000); const INDEX_START: I80F48 = I80F48!(1_000_000);
#[derive(Accounts)] #[derive(Accounts)]
#[instruction(token_index: TokenIndex)]
pub struct RegisterToken<'info> { pub struct RegisterToken<'info> {
#[account( #[account(
mut, mut,
@ -24,7 +25,7 @@ pub struct RegisterToken<'info> {
#[account( #[account(
init, init,
seeds = [group.key().as_ref(), b"TokenBank".as_ref(), mint.key().as_ref()], seeds = [group.key().as_ref(), b"TokenBank".as_ref(), &token_index.to_le_bytes()],
bump, bump,
payer = payer, payer = payer,
space = 8 + std::mem::size_of::<Bank>(), space = 8 + std::mem::size_of::<Bank>(),
@ -33,7 +34,7 @@ pub struct RegisterToken<'info> {
#[account( #[account(
init, init,
seeds = [group.key().as_ref(), b"TokenVault".as_ref(), mint.key().as_ref()], seeds = [group.key().as_ref(), b"TokenVault".as_ref(), &token_index.to_le_bytes()],
bump, bump,
token::authority = group, token::authority = group,
token::mint = mint, token::mint = mint,
@ -74,6 +75,7 @@ pub struct RegisterToken<'info> {
// overwriting config as long as the mint account stays the same? // overwriting config as long as the mint account stays the same?
pub fn register_token( pub fn register_token(
ctx: Context<RegisterToken>, ctx: Context<RegisterToken>,
token_index: TokenIndex,
decimals: u8, decimals: u8,
maint_asset_weight: f32, maint_asset_weight: f32,
init_asset_weight: f32, init_asset_weight: f32,
@ -82,15 +84,7 @@ pub fn register_token(
) -> Result<()> { ) -> Result<()> {
let mut group = ctx.accounts.group.load_mut()?; let mut group = ctx.accounts.group.load_mut()?;
// TODO: Error if mint is already configured (techincally, init of vault will fail) // TODO: Error if mint is already configured (techincally, init of vault will fail)
// TOOD: Error type group.tokens.infos[token_index as usize] = TokenInfo {
// TODO: Should be a function: Tokens::add() or so
let token_index = group
.tokens
.infos
.iter()
.position(|ti| !ti.is_valid())
.ok_or(MangoError::SomeError)?;
group.tokens.infos[token_index] = TokenInfo {
mint: ctx.accounts.mint.key(), mint: ctx.accounts.mint.key(),
decimals, decimals,
bank_bump: *ctx.bumps.get("bank").ok_or(MangoError::SomeError)?, // TODO: error bank_bump: *ctx.bumps.get("bank").ok_or(MangoError::SomeError)?, // TODO: error
@ -113,7 +107,7 @@ pub fn register_token(
maint_liab_weight: I80F48::from_num(maint_liab_weight), maint_liab_weight: I80F48::from_num(maint_liab_weight),
init_liab_weight: I80F48::from_num(init_liab_weight), init_liab_weight: I80F48::from_num(init_liab_weight),
dust: I80F48::ZERO, dust: I80F48::ZERO,
token_index: token_index as TokenIndex, token_index,
}; };
let alt_previous_size = let alt_previous_size =
@ -126,6 +120,7 @@ pub fn register_token(
vault: ctx.accounts.vault.key(), vault: ctx.accounts.vault.key(),
oracle: ctx.accounts.oracle.key(), oracle: ctx.accounts.oracle.key(),
bank: ctx.accounts.bank.key(), bank: ctx.accounts.bank.key(),
token_index,
address_lookup_table: ctx.accounts.address_lookup_table.key(), address_lookup_table: ctx.accounts.address_lookup_table.key(),
address_lookup_table_bank_index: alt_previous_size as u8, address_lookup_table_bank_index: alt_previous_size as u8,
address_lookup_table_oracle_index: alt_previous_size as u8 + 1, address_lookup_table_oracle_index: alt_previous_size as u8 + 1,

View File

@ -22,7 +22,8 @@ pub struct Withdraw<'info> {
mut, mut,
has_one = group, has_one = group,
has_one = vault, has_one = vault,
constraint = bank.load()?.mint == token_account.mint, // the mints of bank/vault/token_account are implicitly the same because
// spl::token::transfer succeeds between token_account and vault
)] )]
pub bank: AccountLoader<'info, Bank>, pub bank: AccountLoader<'info, Bank>,
@ -51,10 +52,10 @@ impl<'info> Withdraw<'info> {
// That would save a lot of computation that needs to go into finding the // That would save a lot of computation that needs to go into finding the
// right index for the mint. // right index for the mint.
pub fn withdraw(ctx: Context<Withdraw>, amount: u64, allow_borrow: bool) -> Result<()> { pub fn withdraw(ctx: Context<Withdraw>, amount: u64, allow_borrow: bool) -> Result<()> {
// Find the mint's token index
let group = ctx.accounts.group.load()?; let group = ctx.accounts.group.load()?;
let mint = ctx.accounts.token_account.mint;
let token_index = group.tokens.index_for_mint(&mint)?; // Find the mint's token index
let token_index = ctx.accounts.bank.load()?.token_index as usize;
// Get the account's position for that token index // Get the account's position for that token index
let mut account = ctx.accounts.account.load_mut()?; let mut account = ctx.accounts.account.load_mut()?;

View File

@ -28,6 +28,7 @@ pub mod mango_v4 {
pub fn register_token( pub fn register_token(
ctx: Context<RegisterToken>, ctx: Context<RegisterToken>,
token_index: TokenIndex,
decimals: u8, decimals: u8,
maint_asset_weight: f32, maint_asset_weight: f32,
init_asset_weight: f32, init_asset_weight: f32,
@ -36,6 +37,7 @@ pub mod mango_v4 {
) -> Result<()> { ) -> Result<()> {
instructions::register_token( instructions::register_token(
ctx, ctx,
token_index,
decimals, decimals,
maint_asset_weight, maint_asset_weight,
init_asset_weight, init_asset_weight,

View File

@ -132,12 +132,7 @@ impl SerumOpenOrdersMap {
} }
pub fn create(&mut self, market_index: SerumMarketIndex) -> Result<&mut SerumOpenOrders> { pub fn create(&mut self, market_index: SerumMarketIndex) -> Result<&mut SerumOpenOrders> {
if self if self.find(market_index).is_some() {
.values
.iter()
.find(|p| p.is_active_for_market(market_index))
.is_some()
{
return err!(MangoError::SomeError); // exists already return err!(MangoError::SomeError); // exists already
} }
if let Some(v) = self.values.iter_mut().find(|p| !p.is_active()) { if let Some(v) = self.values.iter_mut().find(|p| !p.is_active()) {
@ -158,6 +153,12 @@ impl SerumOpenOrdersMap {
pub fn iter_active(&self) -> impl Iterator<Item = &SerumOpenOrders> { pub fn iter_active(&self) -> impl Iterator<Item = &SerumOpenOrders> {
self.values.iter().filter(|p| p.is_active()) self.values.iter().filter(|p| p.is_active())
} }
pub fn find(&self, market_index: SerumMarketIndex) -> Option<&SerumOpenOrders> {
self.values
.iter()
.find(|p| p.is_active_for_market(market_index))
}
} }
#[account(zero_copy)] #[account(zero_copy)]

View File

@ -1,5 +1,7 @@
use anchor_lang::prelude::*; use anchor_lang::prelude::*;
use super::TokenIndex;
// This struct describes which address lookup table can be used to pass // This struct describes which address lookup table can be used to pass
// the accounts that are relevant for this mint. The idea is that clients // the accounts that are relevant for this mint. The idea is that clients
// can load this account to figure out which address maps to use when calling // can load this account to figure out which address maps to use when calling
@ -11,6 +13,7 @@ pub struct MintInfo {
pub bank: Pubkey, pub bank: Pubkey,
pub vault: Pubkey, pub vault: Pubkey,
pub oracle: Pubkey, pub oracle: Pubkey,
pub token_index: TokenIndex,
// describe what address map relevant accounts are found on // describe what address map relevant accounts are found on
pub address_lookup_table: Pubkey, pub address_lookup_table: Pubkey,

View File

@ -234,30 +234,21 @@ impl<'keypair> ClientInstruction for WithdrawInstruction<'keypair> {
// load accounts, find PDAs, find remainingAccounts // load accounts, find PDAs, find remainingAccounts
let token_account: TokenAccount = account_loader.load(&self.token_account).await.unwrap(); let token_account: TokenAccount = account_loader.load(&self.token_account).await.unwrap();
let account: MangoAccount = account_loader.load(&self.account).await.unwrap(); let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
let mint_info = Pubkey::find_program_address(
let bank = Pubkey::find_program_address(
&[ &[
account.group.as_ref(), account.group.as_ref(),
b"TokenBank".as_ref(), b"MintInfo".as_ref(),
token_account.mint.as_ref(),
],
&program_id,
)
.0;
let vault = Pubkey::find_program_address(
&[
account.group.as_ref(),
b"TokenVault".as_ref(),
token_account.mint.as_ref(), token_account.mint.as_ref(),
], ],
&program_id, &program_id,
) )
.0; .0;
let mint_info: MintInfo = account_loader.load(&mint_info).await.unwrap();
let health_check_metas = derive_health_check_remaining_account_metas( let health_check_metas = derive_health_check_remaining_account_metas(
&account_loader, &account_loader,
&account, &account,
Some(bank), Some(mint_info.bank),
false, false,
) )
.await; .await;
@ -266,8 +257,8 @@ impl<'keypair> ClientInstruction for WithdrawInstruction<'keypair> {
group: account.group, group: account.group,
account: self.account, account: self.account,
owner: self.owner.pubkey(), owner: self.owner.pubkey(),
bank, bank: mint_info.bank,
vault, vault: mint_info.vault,
token_account: self.token_account, token_account: self.token_account,
token_program: Token::id(), token_program: Token::id(),
}; };
@ -306,30 +297,21 @@ impl<'keypair> ClientInstruction for DepositInstruction<'keypair> {
// load account so we know its mint // load account so we know its mint
let token_account: TokenAccount = account_loader.load(&self.token_account).await.unwrap(); let token_account: TokenAccount = account_loader.load(&self.token_account).await.unwrap();
let account: MangoAccount = account_loader.load(&self.account).await.unwrap(); let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
let mint_info = Pubkey::find_program_address(
let bank = Pubkey::find_program_address(
&[ &[
account.group.as_ref(), account.group.as_ref(),
b"TokenBank".as_ref(), b"MintInfo".as_ref(),
token_account.mint.as_ref(),
],
&program_id,
)
.0;
let vault = Pubkey::find_program_address(
&[
account.group.as_ref(),
b"TokenVault".as_ref(),
token_account.mint.as_ref(), token_account.mint.as_ref(),
], ],
&program_id, &program_id,
) )
.0; .0;
let mint_info: MintInfo = account_loader.load(&mint_info).await.unwrap();
let health_check_metas = derive_health_check_remaining_account_metas( let health_check_metas = derive_health_check_remaining_account_metas(
&account_loader, &account_loader,
&account, &account,
Some(bank), Some(mint_info.bank),
false, false,
) )
.await; .await;
@ -337,8 +319,8 @@ impl<'keypair> ClientInstruction for DepositInstruction<'keypair> {
let accounts = Self::Accounts { let accounts = Self::Accounts {
group: account.group, group: account.group,
account: self.account, account: self.account,
bank, bank: mint_info.bank,
vault, vault: mint_info.vault,
token_account: self.token_account, token_account: self.token_account,
token_authority: self.token_authority.pubkey(), token_authority: self.token_authority.pubkey(),
token_program: Token::id(), token_program: Token::id(),
@ -356,6 +338,7 @@ impl<'keypair> ClientInstruction for DepositInstruction<'keypair> {
} }
pub struct RegisterTokenInstruction<'keypair> { pub struct RegisterTokenInstruction<'keypair> {
pub token_index: TokenIndex,
pub decimals: u8, pub decimals: u8,
pub maint_asset_weight: f32, pub maint_asset_weight: f32,
pub init_asset_weight: f32, pub init_asset_weight: f32,
@ -378,6 +361,7 @@ impl<'keypair> ClientInstruction for RegisterTokenInstruction<'keypair> {
) -> (Self::Accounts, instruction::Instruction) { ) -> (Self::Accounts, instruction::Instruction) {
let program_id = mango_v4::id(); let program_id = mango_v4::id();
let instruction = Self::Instruction { let instruction = Self::Instruction {
token_index: self.token_index,
decimals: self.decimals, decimals: self.decimals,
maint_asset_weight: self.maint_asset_weight, maint_asset_weight: self.maint_asset_weight,
init_asset_weight: self.init_asset_weight, init_asset_weight: self.init_asset_weight,
@ -389,7 +373,7 @@ impl<'keypair> ClientInstruction for RegisterTokenInstruction<'keypair> {
&[ &[
self.group.as_ref(), self.group.as_ref(),
b"TokenBank".as_ref(), b"TokenBank".as_ref(),
self.mint.as_ref(), &self.token_index.to_le_bytes(),
], ],
&program_id, &program_id,
) )
@ -398,7 +382,7 @@ impl<'keypair> ClientInstruction for RegisterTokenInstruction<'keypair> {
&[ &[
self.group.as_ref(), self.group.as_ref(),
b"TokenVault".as_ref(), b"TokenVault".as_ref(),
self.mint.as_ref(), &self.token_index.to_le_bytes(),
], ],
&program_id, &program_id,
) )
@ -708,3 +692,46 @@ impl<'keypair> ClientInstruction for CreateSerumOpenOrdersInstruction<'keypair>
vec![self.owner, self.payer] vec![self.owner, self.payer]
} }
} }
/*
pub struct PlaceSerumOrderInstruction<'keypair> {
pub account: Pubkey,
pub serum_market: Pubkey,
pub owner: &'keypair Keypair,
}
#[async_trait::async_trait(?Send)]
impl<'keypair> ClientInstruction for PlaceSerumOrderInstruction<'keypair> {
type Accounts = mango_v4::accounts::PlaceSerumOrder;
type Instruction = mango_v4::instruction::PlaceSerumOrder;
async fn to_instruction(
&self,
account_loader: impl ClientAccountLoader + 'async_trait,
) -> (Self::Accounts, instruction::Instruction) {
let program_id = mango_v4::id();
let instruction = Self::Instruction {};
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
let serum_market: SerumMarket = account_loader.load(&self.serum_market).await.unwrap();
let open_orders = account.serum_open_orders_map.find(serum_market.market_index).unwrap().open_orders;
let accounts = Self::Accounts {
group: account.group,
account: self.account,
open_orders,
serum_market: self.serum_market,
serum_program: serum_market.serum_program,
serum_market_external: serum_market.serum_market_external,
owner: self.owner.pubkey(),
payer: self.payer.pubkey(),
system_program: System::id(),
rent: sysvar::rent::Rent::id(),
};
let instruction = make_instruction(program_id, &accounts, instruction);
(accounts, instruction)
}
fn signers(&self) -> Vec<&Keypair> {
vec![self.owner]
}
}*/

View File

@ -72,6 +72,7 @@ async fn test_basic() -> Result<(), TransportError> {
let register_token_accounts = send_tx( let register_token_accounts = send_tx(
solana, solana,
RegisterTokenInstruction { RegisterTokenInstruction {
token_index: 0,
decimals: mint0.decimals, decimals: mint0.decimals,
maint_asset_weight: 0.9, maint_asset_weight: 0.9,
init_asset_weight: 0.8, init_asset_weight: 0.8,

View File

@ -5,6 +5,7 @@ use solana_program_test::*;
use solana_sdk::signature::Keypair; use solana_sdk::signature::Keypair;
use mango_v4::address_lookup_table; use mango_v4::address_lookup_table;
use mango_v4::state::*;
use program_test::*; use program_test::*;
mod program_test; mod program_test;
@ -51,7 +52,7 @@ async fn test_group_address_lookup_tables() -> Result<()> {
// SETUP: Register three mints (and make oracles for them) // SETUP: Register three mints (and make oracles for them)
// //
let register_mint = |mint: MintCookie, address_lookup_table: Pubkey| async move { let register_mint = |index: TokenIndex, mint: MintCookie, address_lookup_table: Pubkey| async move {
let create_stub_oracle_accounts = send_tx( let create_stub_oracle_accounts = send_tx(
solana, solana,
CreateStubOracle { CreateStubOracle {
@ -75,6 +76,7 @@ async fn test_group_address_lookup_tables() -> Result<()> {
let register_token_accounts = send_tx( let register_token_accounts = send_tx(
solana, solana,
RegisterTokenInstruction { RegisterTokenInstruction {
token_index: index,
decimals: mint.decimals, decimals: mint.decimals,
maint_asset_weight: 0.9, maint_asset_weight: 0.9,
init_asset_weight: 0.8, init_asset_weight: 0.8,
@ -100,9 +102,9 @@ async fn test_group_address_lookup_tables() -> Result<()> {
solana.advance_by_slots(1).await; // to get a different address solana.advance_by_slots(1).await; // to get a different address
let address_lookup_table2 = solana.create_address_lookup_table(admin, payer).await; let address_lookup_table2 = solana.create_address_lookup_table(admin, payer).await;
let (oracle0, bank0) = register_mint(mint0.clone(), address_lookup_table1).await; let (oracle0, bank0) = register_mint(0, mint0.clone(), address_lookup_table1).await;
let (oracle1, bank1) = register_mint(mint1.clone(), address_lookup_table1).await; let (oracle1, bank1) = register_mint(1, mint1.clone(), address_lookup_table1).await;
let (oracle2, bank2) = register_mint(mint2.clone(), address_lookup_table2).await; let (oracle2, bank2) = register_mint(2, mint2.clone(), address_lookup_table2).await;
// check the resulting address maps // check the resulting address maps
let data = solana let data = solana

View File

@ -87,6 +87,7 @@ async fn test_margin_trade() -> Result<(), TransportError> {
let register_token_accounts = send_tx( let register_token_accounts = send_tx(
solana, solana,
RegisterTokenInstruction { RegisterTokenInstruction {
token_index: 0,
decimals: mint0.decimals, decimals: mint0.decimals,
maint_asset_weight: 0.9, maint_asset_weight: 0.9,
init_asset_weight: 0.8, init_asset_weight: 0.8,

View File

@ -65,7 +65,7 @@ async fn test_position_lifetime() -> Result<()> {
let address_lookup_table = solana.create_address_lookup_table(admin, payer).await; let address_lookup_table = solana.create_address_lookup_table(admin, payer).await;
let register_mint = |mint: MintCookie| async move { let register_mint = |index: TokenIndex, mint: MintCookie| async move {
let create_stub_oracle_accounts = send_tx( let create_stub_oracle_accounts = send_tx(
solana, solana,
CreateStubOracle { CreateStubOracle {
@ -89,6 +89,7 @@ async fn test_position_lifetime() -> Result<()> {
let register_token_accounts = send_tx( let register_token_accounts = send_tx(
solana, solana,
RegisterTokenInstruction { RegisterTokenInstruction {
token_index: index,
decimals: mint.decimals, decimals: mint.decimals,
maint_asset_weight: 0.9, maint_asset_weight: 0.9,
init_asset_weight: 0.8, init_asset_weight: 0.8,
@ -107,9 +108,9 @@ async fn test_position_lifetime() -> Result<()> {
(oracle, bank) (oracle, bank)
}; };
register_mint(mint0.clone()).await; register_mint(0, mint0.clone()).await;
register_mint(mint1.clone()).await; register_mint(1, mint1.clone()).await;
register_mint(mint2.clone()).await; register_mint(2, mint2.clone()).await;
// //
// SETUP: Put some tokens into the funding account to allow borrowing // SETUP: Put some tokens into the funding account to allow borrowing

View File

@ -51,7 +51,7 @@ async fn test_serum() -> Result<(), TransportError> {
// SETUP: Register mints (and make oracles for them) // SETUP: Register mints (and make oracles for them)
// //
let register_mint = |mint: MintCookie, address_lookup_table: Pubkey| async move { let register_mint = |index: TokenIndex, mint: MintCookie, address_lookup_table: Pubkey| async move {
let create_stub_oracle_accounts = send_tx( let create_stub_oracle_accounts = send_tx(
solana, solana,
CreateStubOracle { CreateStubOracle {
@ -75,6 +75,7 @@ async fn test_serum() -> Result<(), TransportError> {
let register_token_accounts = send_tx( let register_token_accounts = send_tx(
solana, solana,
RegisterTokenInstruction { RegisterTokenInstruction {
token_index: index,
decimals: mint.decimals, decimals: mint.decimals,
maint_asset_weight: 0.9, maint_asset_weight: 0.9,
init_asset_weight: 0.8, init_asset_weight: 0.8,
@ -95,8 +96,12 @@ async fn test_serum() -> Result<(), TransportError> {
}; };
let address_lookup_table = solana.create_address_lookup_table(admin, payer).await; let address_lookup_table = solana.create_address_lookup_table(admin, payer).await;
let (_oracle0, _bank0) = register_mint(mint0.clone(), address_lookup_table).await; let base_token_index = 0;
let (_oracle1, _bank1) = register_mint(mint1.clone(), address_lookup_table).await; let (_oracle0, _bank0) =
register_mint(base_token_index, mint0.clone(), address_lookup_table).await;
let quote_token_index = 1;
let (_oracle1, _bank1) =
register_mint(quote_token_index, mint1.clone(), address_lookup_table).await;
// //
// TEST: Register a serum market // TEST: Register a serum market
@ -108,8 +113,8 @@ async fn test_serum() -> Result<(), TransportError> {
admin, admin,
serum_program: context.serum.program_id, serum_program: context.serum.program_id,
serum_market_external: serum_market_cookie.market, serum_market_external: serum_market_cookie.market,
base_token_index: 0, // TODO: better way of getting these numbers base_token_index,
quote_token_index: 1, quote_token_index,
payer, payer,
}, },
) )