From a9a03b97ac199bba67c4d3786fce1236b1891965 Mon Sep 17 00:00:00 2001 From: microwavedcola1 <89031858+microwavedcola1@users.noreply.github.com> Date: Mon, 1 Aug 2022 18:46:45 +0200 Subject: [PATCH] mc/registration time (#132) * registration time Signed-off-by: microwavedcola1 * fix from review Signed-off-by: microwavedcola1 * fix from review Signed-off-by: microwavedcola1 * mc/u32 numbers - consistent numbers in pdas (#133) * consistent numbers in pdas Signed-off-by: microwavedcola1 * fix Signed-off-by: microwavedcola1 --- client/src/client.rs | 2 +- .../src/instructions/account_create.rs | 4 +- .../src/instructions/perp_create_market.rs | 1 + .../instructions/serum3_register_market.rs | 1 + .../src/instructions/token_add_bank.rs | 7 +- .../src/instructions/token_register.rs | 8 +- programs/mango-v4/src/lib.rs | 6 +- programs/mango-v4/src/state/bank.rs | 11 +- programs/mango-v4/src/state/mango_account.rs | 6 +- programs/mango-v4/src/state/mint_info.rs | 4 +- programs/mango-v4/src/state/perp_market.rs | 4 +- programs/mango-v4/src/state/serum3_market.rs | 4 +- .../tests/program_test/mango_client.rs | 16 +-- ts/client/src/accounts/bank.ts | 3 + ts/client/src/accounts/perp.ts | 3 + ts/client/src/accounts/serum3.ts | 4 + ts/client/src/mango_v4.ts | 128 +++++++++++++----- 17 files changed, 144 insertions(+), 68 deletions(-) diff --git a/client/src/client.rs b/client/src/client.rs index 83029d0b1..013d89bb0 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -112,7 +112,7 @@ impl MangoClient { }); let account_num = match mango_account_tuples.last() { Some(tuple) => tuple.1.fixed.account_num + 1, - None => 0u8, + None => 0u32, }; program .request() diff --git a/programs/mango-v4/src/instructions/account_create.rs b/programs/mango-v4/src/instructions/account_create.rs index adea30557..d55741bca 100644 --- a/programs/mango-v4/src/instructions/account_create.rs +++ b/programs/mango-v4/src/instructions/account_create.rs @@ -5,7 +5,7 @@ use crate::state::*; use crate::util::fill32_from_str; #[derive(Accounts)] -#[instruction(account_num: u8, account_size: AccountSize)] +#[instruction(account_num: u32, account_size: AccountSize)] pub struct AccountCreate<'info> { pub group: AccountLoader<'info, Group>, @@ -28,7 +28,7 @@ pub struct AccountCreate<'info> { pub fn account_create( ctx: Context, - account_num: u8, + account_num: u32, account_size: AccountSize, name: String, ) -> Result<()> { diff --git a/programs/mango-v4/src/instructions/perp_create_market.rs b/programs/mango-v4/src/instructions/perp_create_market.rs index 80d5c52c5..8c0baee5e 100644 --- a/programs/mango-v4/src/instructions/perp_create_market.rs +++ b/programs/mango-v4/src/instructions/perp_create_market.rs @@ -96,6 +96,7 @@ pub fn perp_create_market( base_token_decimals, perp_market_index, base_token_index: base_token_index_opt.ok_or(TokenIndex::MAX).unwrap(), + registration_time: Clock::get()?.unix_timestamp, padding1: Default::default(), padding2: Default::default(), reserved: [0; 128], diff --git a/programs/mango-v4/src/instructions/serum3_register_market.rs b/programs/mango-v4/src/instructions/serum3_register_market.rs index aa0fc0e75..228b8bd97 100644 --- a/programs/mango-v4/src/instructions/serum3_register_market.rs +++ b/programs/mango-v4/src/instructions/serum3_register_market.rs @@ -77,6 +77,7 @@ pub fn serum3_register_market( bump: *ctx.bumps.get("serum_market").ok_or(MangoError::SomeError)?, padding1: Default::default(), padding2: Default::default(), + registration_time: Clock::get()?.unix_timestamp, reserved: [0; 128], }; diff --git a/programs/mango-v4/src/instructions/token_add_bank.rs b/programs/mango-v4/src/instructions/token_add_bank.rs index a1de92419..c5cb957ed 100644 --- a/programs/mango-v4/src/instructions/token_add_bank.rs +++ b/programs/mango-v4/src/instructions/token_add_bank.rs @@ -7,7 +7,7 @@ use anchor_spl::token::{Mint, Token, TokenAccount}; use crate::state::*; #[derive(Accounts)] -#[instruction(token_index: TokenIndex, bank_num: u64)] +#[instruction(token_index: TokenIndex, bank_num: u32)] pub struct TokenAddBank<'info> { #[account( has_one = admin, @@ -75,10 +75,11 @@ pub struct TokenAddBank<'info> { // TODO: should this be "configure_mint", we pass an explicit index, and allow // overwriting config as long as the mint account stays the same? #[allow(clippy::too_many_arguments)] +#[allow(unused_variables)] pub fn token_add_bank( ctx: Context, - _token_index: TokenIndex, - bank_num: u64, + token_index: TokenIndex, + bank_num: u32, ) -> Result<()> { // TODO: Error if mint is already configured (technically, init of vault will fail) diff --git a/programs/mango-v4/src/instructions/token_register.rs b/programs/mango-v4/src/instructions/token_register.rs index 51db22576..1e09d4278 100644 --- a/programs/mango-v4/src/instructions/token_register.rs +++ b/programs/mango-v4/src/instructions/token_register.rs @@ -12,7 +12,7 @@ use crate::util::fill16_from_str; pub const INDEX_START: I80F48 = I80F48!(1_000_000); #[derive(Accounts)] -#[instruction(token_index: TokenIndex, bank_num: u64)] +#[instruction(token_index: TokenIndex, bank_num: u32)] pub struct TokenRegister<'info> { #[account( has_one = admin, @@ -91,7 +91,7 @@ pub struct InterestRateParams { pub fn token_register( ctx: Context, token_index: TokenIndex, - bank_num: u64, + bank_num: u32, name: String, oracle_config: OracleConfig, interest_rate_params: InterestRateParams, @@ -117,8 +117,8 @@ pub fn token_register( let mut bank = ctx.accounts.bank.load_init()?; *bank = Bank { - name: fill16_from_str(name)?, group: ctx.accounts.group.key(), + name: fill16_from_str(name)?, mint: ctx.accounts.mint.key(), vault: ctx.accounts.vault.key(), oracle: ctx.accounts.oracle.key(), @@ -154,7 +154,6 @@ pub fn token_register( bump: *ctx.bumps.get("bank").ok_or(MangoError::SomeError)?, mint_decimals: ctx.accounts.mint.decimals, bank_num: 0, - padding: Default::default(), reserved: [0; 256], }; @@ -175,6 +174,7 @@ pub fn token_register( token_index, address_lookup_table_bank_index: alt_previous_size as u8, address_lookup_table_oracle_index: alt_previous_size as u8 + 1, + registration_time: Clock::get()?.unix_timestamp, padding1: Default::default(), padding2: Default::default(), reserved: [0; 256], diff --git a/programs/mango-v4/src/lib.rs b/programs/mango-v4/src/lib.rs index 5c1549b87..132410f84 100644 --- a/programs/mango-v4/src/lib.rs +++ b/programs/mango-v4/src/lib.rs @@ -57,7 +57,7 @@ pub mod mango_v4 { pub fn token_register( ctx: Context, token_index: TokenIndex, - bank_num: u64, + bank_num: u32, name: String, oracle_config: OracleConfig, interest_rate_params: InterestRateParams, @@ -121,7 +121,7 @@ pub mod mango_v4 { pub fn token_add_bank( ctx: Context, token_index: TokenIndex, - bank_num: u64, + bank_num: u32, ) -> Result<()> { instructions::token_add_bank(ctx, token_index, bank_num) } @@ -139,7 +139,7 @@ pub mod mango_v4 { pub fn account_create( ctx: Context, - account_num: u8, + account_num: u32, account_size: AccountSize, name: String, ) -> Result<()> { diff --git a/programs/mango-v4/src/state/bank.rs b/programs/mango-v4/src/state/bank.rs index 177df3bb4..194a6cf08 100644 --- a/programs/mango-v4/src/state/bank.rs +++ b/programs/mango-v4/src/state/bank.rs @@ -91,15 +91,13 @@ pub struct Bank { pub mint_decimals: u8, - pub padding: [u8; 4], - - pub bank_num: u64, + pub bank_num: u32, pub reserved: [u8; 256], } const_assert_eq!( size_of::(), - 16 + 32 * 4 + 8 * 2 + 16 * 23 + 2 * 8 + 2 + 1 + 1 + 4 + 8 + 256 + 32 + 16 + 32 * 3 + 16 + 16 * 6 + 8 * 2 + 16 * 16 + 8 * 2 + 2 + 1 * 2 + 4 + 256 ); const_assert_eq!(size_of::() % 8, 0); @@ -153,12 +151,12 @@ impl std::fmt::Debug for Bank { } impl Bank { - pub fn from_existing_bank(existing_bank: &Bank, vault: Pubkey, bank_num: u64) -> Self { + pub fn from_existing_bank(existing_bank: &Bank, vault: Pubkey, bank_num: u32) -> Self { Self { name: existing_bank.name, group: existing_bank.group, mint: existing_bank.mint, - vault: vault, + vault, oracle: existing_bank.oracle, oracle_config: existing_bank.oracle_config, deposit_index: existing_bank.deposit_index, @@ -190,7 +188,6 @@ impl Bank { token_index: existing_bank.token_index, bump: existing_bank.bump, mint_decimals: existing_bank.mint_decimals, - padding: Default::default(), reserved: [0; 256], bank_num, } diff --git a/programs/mango-v4/src/state/mango_account.rs b/programs/mango-v4/src/state/mango_account.rs index a87ee54fe..c3cc654df 100644 --- a/programs/mango-v4/src/state/mango_account.rs +++ b/programs/mango-v4/src/state/mango_account.rs @@ -221,16 +221,16 @@ pub struct MangoAccountFixed { pub owner: Pubkey, pub name: [u8; 32], pub delegate: Pubkey, + pub account_num: u32, being_liquidated: u8, is_bankrupt: u8, - pub account_num: u8, pub bump: u8, - pub padding: [u8; 4], + pub padding: [u8; 1], pub net_deposits: f32, pub net_settled: f32, pub reserved: [u8; 256], } -const_assert_eq!(size_of::(), 32 * 4 + 4 + 4 + 2 * 4 + 256); +const_assert_eq!(size_of::(), 32 * 4 + 8 + 2 * 4 + 256); const_assert_eq!(size_of::() % 8, 0); impl MangoAccountFixed { diff --git a/programs/mango-v4/src/state/mint_info.rs b/programs/mango-v4/src/state/mint_info.rs index 5c7144df7..5de80eef0 100644 --- a/programs/mango-v4/src/state/mint_info.rs +++ b/programs/mango-v4/src/state/mint_info.rs @@ -34,11 +34,13 @@ pub struct MintInfo { pub padding2: [u8; 6], + pub registration_time: i64, + pub reserved: [u8; 256], } const_assert_eq!( size_of::(), - MAX_BANKS * 2 * 32 + 4 * 32 + 2 + 6 + 2 + 6 + 256 + MAX_BANKS * 2 * 32 + 4 * 32 + 2 + 6 + 2 + 8 + 6 + 256 ); const_assert_eq!(size_of::() % 8, 0); diff --git a/programs/mango-v4/src/state/perp_market.rs b/programs/mango-v4/src/state/perp_market.rs index dc20cd4a6..010ddf435 100644 --- a/programs/mango-v4/src/state/perp_market.rs +++ b/programs/mango-v4/src/state/perp_market.rs @@ -88,12 +88,14 @@ pub struct PerpMarket { pub padding2: [u8; 6], + pub registration_time: i64, + pub reserved: [u8; 128], } const_assert_eq!( size_of::(), - 32 + 2 + 2 + 4 + 16 + 32 + 16 + 32 * 3 + 8 * 2 + 16 * 11 + 8 * 2 + 8 * 2 + 16 + 2 + 6 + 128 + 32 + 2 + 2 + 4 + 16 + 32 + 16 + 32 * 3 + 8 * 2 + 16 * 11 + 8 * 2 + 8 * 2 + 16 + 2 + 6 + 8 + 128 ); const_assert_eq!(size_of::() % 8, 0); diff --git a/programs/mango-v4/src/state/serum3_market.rs b/programs/mango-v4/src/state/serum3_market.rs index 350bd1d1b..8d066fb61 100644 --- a/programs/mango-v4/src/state/serum3_market.rs +++ b/programs/mango-v4/src/state/serum3_market.rs @@ -26,11 +26,13 @@ pub struct Serum3Market { pub padding2: [u8; 5], + pub registration_time: i64, + pub reserved: [u8; 128], } const_assert_eq!( size_of::(), - 32 + 2 + 2 + 4 + 16 + 2 * 32 + 2 + 1 + 5 + 128 + 32 + 2 + 2 + 4 + 16 + 2 * 32 + 2 + 1 + 5 + 8 + 128 ); const_assert_eq!(size_of::() % 8, 0); diff --git a/programs/mango-v4/tests/program_test/mango_client.rs b/programs/mango-v4/tests/program_test/mango_client.rs index 95537b57a..41fcb05f9 100644 --- a/programs/mango-v4/tests/program_test/mango_client.rs +++ b/programs/mango-v4/tests/program_test/mango_client.rs @@ -148,7 +148,7 @@ async fn get_mint_info_by_token_index( account.fixed.group.as_ref(), b"Bank".as_ref(), &token_index.to_le_bytes(), - &0u64.to_le_bytes(), + &0u32.to_le_bytes(), ], &mango_v4::id(), ) @@ -657,7 +657,7 @@ impl<'keypair> ClientInstruction for TokenRegisterInstruction<'keypair> { self.group.as_ref(), b"Bank".as_ref(), &self.token_index.to_le_bytes(), - &0u64.to_le_bytes(), + &0u32.to_le_bytes(), ], &program_id, ) @@ -667,7 +667,7 @@ impl<'keypair> ClientInstruction for TokenRegisterInstruction<'keypair> { self.group.as_ref(), b"Vault".as_ref(), &self.token_index.to_le_bytes(), - &0u64.to_le_bytes(), + &0u32.to_le_bytes(), ], &program_id, ) @@ -721,7 +721,7 @@ impl<'keypair> ClientInstruction for TokenRegisterInstruction<'keypair> { pub struct TokenAddBankInstruction<'keypair> { pub token_index: TokenIndex, - pub bank_num: u64, + pub bank_num: u32, pub group: Pubkey, pub admin: &'keypair Keypair, @@ -747,7 +747,7 @@ impl<'keypair> ClientInstruction for TokenAddBankInstruction<'keypair> { self.group.as_ref(), b"Bank".as_ref(), &self.token_index.to_le_bytes(), - &0u64.to_le_bytes(), + &0u32.to_le_bytes(), ], &program_id, ) @@ -1112,7 +1112,7 @@ impl<'keypair> ClientInstruction for GroupCloseInstruction<'keypair> { } pub struct AccountCreateInstruction<'keypair> { - pub account_num: u8, + pub account_num: u32, pub account_size: AccountSize, pub group: Pubkey, pub owner: &'keypair Keypair, @@ -1162,7 +1162,7 @@ impl<'keypair> ClientInstruction for AccountCreateInstruction<'keypair> { } pub struct AccountExpandInstruction<'keypair> { - pub account_num: u8, + pub account_num: u32, pub group: Pubkey, pub owner: &'keypair Keypair, pub payer: &'keypair Keypair, @@ -1207,7 +1207,7 @@ impl<'keypair> ClientInstruction for AccountExpandInstruction<'keypair> { } pub struct AccountEditInstruction<'keypair> { - pub account_num: u8, + pub account_num: u32, pub group: Pubkey, pub owner: &'keypair Keypair, pub name: String, diff --git a/ts/client/src/accounts/bank.ts b/ts/client/src/accounts/bank.ts index c2f08b8a4..869b4a858 100644 --- a/ts/client/src/accounts/bank.ts +++ b/ts/client/src/accounts/bank.ts @@ -288,6 +288,7 @@ export class MintInfo { addressLookupTableBankIndex: Number; addressLookupTableOracleIndex: Number; reserved: unknown; + registrationTime: BN; }, ) { return new MintInfo( @@ -297,6 +298,7 @@ export class MintInfo { obj.vaults, obj.oracle, obj.tokenIndex, + obj.registrationTime, ); } @@ -307,6 +309,7 @@ export class MintInfo { public vaults: PublicKey[], public oracle: PublicKey, public tokenIndex: number, + registrationTime: BN, ) {} public firstBank(): PublicKey { diff --git a/ts/client/src/accounts/perp.ts b/ts/client/src/accounts/perp.ts index 1ee75daee..6a66aa1e8 100644 --- a/ts/client/src/accounts/perp.ts +++ b/ts/client/src/accounts/perp.ts @@ -43,6 +43,7 @@ export class PerpMarket { perpMarketIndex: number; baseTokenIndex: number; quoteTokenIndex: number; + registrationTime: BN; }, ): PerpMarket { return new PerpMarket( @@ -70,6 +71,7 @@ export class PerpMarket { obj.perpMarketIndex, obj.baseTokenIndex, obj.quoteTokenIndex, + obj.registrationTime, ); } @@ -98,6 +100,7 @@ export class PerpMarket { public perpMarketIndex: number, public baseTokenIndex: number, public quoteTokenIndex: number, + public registrationTime: BN, ) { this.name = utf8.decode(new Uint8Array(name)).split('\x00')[0]; this.maintAssetWeight = I80F48.from(maintAssetWeight); diff --git a/ts/client/src/accounts/serum3.ts b/ts/client/src/accounts/serum3.ts index ac8dcb877..0c00ffd65 100644 --- a/ts/client/src/accounts/serum3.ts +++ b/ts/client/src/accounts/serum3.ts @@ -1,5 +1,6 @@ import { utf8 } from '@project-serum/anchor/dist/cjs/utils/bytes'; import { PublicKey } from '@solana/web3.js'; +import BN from 'bn.js'; export class Serum3Market { public name: string; @@ -15,6 +16,7 @@ export class Serum3Market { quoteTokenIndex: number; bump: number; reserved: unknown; + registrationTime: BN; }, ): Serum3Market { return new Serum3Market( @@ -26,6 +28,7 @@ export class Serum3Market { obj.marketIndex, obj.baseTokenIndex, obj.quoteTokenIndex, + obj.registrationTime, ); } @@ -38,6 +41,7 @@ export class Serum3Market { public marketIndex: number, public baseTokenIndex: number, public quoteTokenIndex: number, + public registrationTime: BN, ) { this.name = utf8.decode(new Uint8Array(name)).split('\x00')[0]; } diff --git a/ts/client/src/mango_v4.ts b/ts/client/src/mango_v4.ts index f19d227ba..5ed37e8da 100644 --- a/ts/client/src/mango_v4.ts +++ b/ts/client/src/mango_v4.ts @@ -2723,7 +2723,7 @@ export type MangoV4 = { "type": { "array": [ "u8", - 128 + 256 ] } } @@ -2794,7 +2794,7 @@ export type MangoV4 = { "type": { "array": [ "u8", - 128 + 256 ] } } @@ -2875,6 +2875,19 @@ export type MangoV4 = { ] } }, + { + "name": "headerVersion", + "type": "u8" + }, + { + "name": "padding0", + "type": { + "array": [ + "u8", + 7 + ] + } + }, { "name": "padding1", "type": "u32" @@ -2995,12 +3008,16 @@ export type MangoV4 = { ] } }, + { + "name": "registrationTime", + "type": "i64" + }, { "name": "reserved", "type": { "array": [ "u8", - 128 + 256 ] } } @@ -3103,7 +3120,7 @@ export type MangoV4 = { "type": { "array": [ "u8", - 128 + 256 ] } } @@ -3332,6 +3349,10 @@ export type MangoV4 = { ] } }, + { + "name": "registrationTime", + "type": "i64" + }, { "name": "reserved", "type": { @@ -3404,6 +3425,10 @@ export type MangoV4 = { ] } }, + { + "name": "registrationTime", + "type": "i64" + }, { "name": "reserved", "type": { @@ -3740,7 +3765,7 @@ export type MangoV4 = { "type": { "array": [ "u8", - 64 + 40 ] } } @@ -4798,66 +4823,71 @@ export type MangoV4 = { }, { "code": 6001, + "name": "NotImplementedError", + "msg": "" + }, + { + "code": 6002, "name": "MathError", "msg": "checked math error" }, { - "code": 6002, + "code": 6003, "name": "UnexpectedOracle", "msg": "" }, { - "code": 6003, + "code": 6004, "name": "UnknownOracleType", "msg": "oracle type cannot be determined" }, { - "code": 6004, + "code": 6005, "name": "InvalidFlashLoanTargetCpiProgram", "msg": "" }, { - "code": 6005, + "code": 6006, "name": "HealthMustBePositive", "msg": "health must be positive" }, { - "code": 6006, + "code": 6007, "name": "HealthMustBeNegative", "msg": "health must be negative" }, { - "code": 6007, + "code": 6008, "name": "IsBankrupt", "msg": "the account is bankrupt" }, { - "code": 6008, + "code": 6009, "name": "IsNotBankrupt", "msg": "the account is not bankrupt" }, { - "code": 6009, + "code": 6010, "name": "NoFreeTokenPositionIndex", "msg": "no free token position index" }, { - "code": 6010, + "code": 6011, "name": "NoFreeSerum3OpenOrdersIndex", "msg": "no free serum3 open orders index" }, { - "code": 6011, + "code": 6012, "name": "NoFreePerpPositionIndex", "msg": "no free perp position index" }, { - "code": 6012, + "code": 6013, "name": "Serum3OpenOrdersExistAlready", "msg": "serum3 open orders exist already" }, { - "code": 6013, + "code": 6014, "name": "InsufficentBankVaultFunds", "msg": "bank vault has insufficent funds" } @@ -7589,7 +7619,7 @@ export const IDL: MangoV4 = { "type": { "array": [ "u8", - 128 + 256 ] } } @@ -7660,7 +7690,7 @@ export const IDL: MangoV4 = { "type": { "array": [ "u8", - 128 + 256 ] } } @@ -7741,6 +7771,19 @@ export const IDL: MangoV4 = { ] } }, + { + "name": "headerVersion", + "type": "u8" + }, + { + "name": "padding0", + "type": { + "array": [ + "u8", + 7 + ] + } + }, { "name": "padding1", "type": "u32" @@ -7861,12 +7904,16 @@ export const IDL: MangoV4 = { ] } }, + { + "name": "registrationTime", + "type": "i64" + }, { "name": "reserved", "type": { "array": [ "u8", - 128 + 256 ] } } @@ -7969,7 +8016,7 @@ export const IDL: MangoV4 = { "type": { "array": [ "u8", - 128 + 256 ] } } @@ -8198,6 +8245,10 @@ export const IDL: MangoV4 = { ] } }, + { + "name": "registrationTime", + "type": "i64" + }, { "name": "reserved", "type": { @@ -8270,6 +8321,10 @@ export const IDL: MangoV4 = { ] } }, + { + "name": "registrationTime", + "type": "i64" + }, { "name": "reserved", "type": { @@ -8606,7 +8661,7 @@ export const IDL: MangoV4 = { "type": { "array": [ "u8", - 64 + 40 ] } } @@ -9664,66 +9719,71 @@ export const IDL: MangoV4 = { }, { "code": 6001, + "name": "NotImplementedError", + "msg": "" + }, + { + "code": 6002, "name": "MathError", "msg": "checked math error" }, { - "code": 6002, + "code": 6003, "name": "UnexpectedOracle", "msg": "" }, { - "code": 6003, + "code": 6004, "name": "UnknownOracleType", "msg": "oracle type cannot be determined" }, { - "code": 6004, + "code": 6005, "name": "InvalidFlashLoanTargetCpiProgram", "msg": "" }, { - "code": 6005, + "code": 6006, "name": "HealthMustBePositive", "msg": "health must be positive" }, { - "code": 6006, + "code": 6007, "name": "HealthMustBeNegative", "msg": "health must be negative" }, { - "code": 6007, + "code": 6008, "name": "IsBankrupt", "msg": "the account is bankrupt" }, { - "code": 6008, + "code": 6009, "name": "IsNotBankrupt", "msg": "the account is not bankrupt" }, { - "code": 6009, + "code": 6010, "name": "NoFreeTokenPositionIndex", "msg": "no free token position index" }, { - "code": 6010, + "code": 6011, "name": "NoFreeSerum3OpenOrdersIndex", "msg": "no free serum3 open orders index" }, { - "code": 6011, + "code": 6012, "name": "NoFreePerpPositionIndex", "msg": "no free perp position index" }, { - "code": 6012, + "code": 6013, "name": "Serum3OpenOrdersExistAlready", "msg": "serum3 open orders exist already" }, { - "code": 6013, + "code": 6014, "name": "InsufficentBankVaultFunds", "msg": "bank vault has insufficent funds" }