From bd5f8746095f015a833d2c448ce3cb2a5c2ba529 Mon Sep 17 00:00:00 2001 From: Riordan Panayides Date: Fri, 12 Aug 2022 13:36:50 +0100 Subject: [PATCH 1/7] Add glibc to runtime image --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 93fed90ec..dfd91d14e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,5 +17,5 @@ RUN --mount=type=cache,target=/usr/local/cargo,from=rust,source=/usr/local/cargo RUN --mount=type=cache,target=target mkdir .bin && cp target/release/keeper target/release/liquidator .bin/ FROM debian:buster-slim as run -RUN apt-get update && apt-get -y install ca-certificates +RUN apt-get update && apt-get -y install ca-certificates libc6 COPY --from=build /app/.bin/* /usr/local/bin/ From fa829805086e371ea7c982aa965505fdf7a54c61 Mon Sep 17 00:00:00 2001 From: Riordan Panayides Date: Fri, 12 Aug 2022 14:17:18 +0100 Subject: [PATCH 2/7] Upgrade docker runtime distro --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index dfd91d14e..27e720e1c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,6 +16,6 @@ RUN --mount=type=cache,target=/usr/local/cargo,from=rust,source=/usr/local/cargo # Copy bins out of cache RUN --mount=type=cache,target=target mkdir .bin && cp target/release/keeper target/release/liquidator .bin/ -FROM debian:buster-slim as run +FROM debian:bullseye-slim as run RUN apt-get update && apt-get -y install ca-certificates libc6 COPY --from=build /app/.bin/* /usr/local/bin/ From 8335c5495ec7442f79581047c7fbcf6c30bb27c8 Mon Sep 17 00:00:00 2001 From: Riordan Panayides Date: Fri, 12 Aug 2022 15:31:53 +0100 Subject: [PATCH 3/7] Fix liquidator command --- liquidator/Dockerfile.liquidator | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liquidator/Dockerfile.liquidator b/liquidator/Dockerfile.liquidator index 6257911e5..9935d6b37 100644 --- a/liquidator/Dockerfile.liquidator +++ b/liquidator/Dockerfile.liquidator @@ -2,4 +2,4 @@ # heroku container:push keeper -R -a HEROKU_APP_NAME # heroku container:release -a HEROKU_APP_NAME FROM us-docker.pkg.dev/mango-markets/gcr.io/mango-v4:latest -ENTRYPOINT ["liquidator"] +CMD ["liquidator"] From a3067e24484aa6b6314f70fbae8aa6ec279ddc9e Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Fri, 12 Aug 2022 16:05:32 +0200 Subject: [PATCH 4/7] Avoid custom Debug impls by using derivative crate --- Cargo.lock | 12 ++++ programs/mango-v4/Cargo.toml | 1 + .../src/instructions/account_create.rs | 4 +- .../mango-v4/src/instructions/account_edit.rs | 6 +- .../src/instructions/perp_create_market.rs | 4 +- .../instructions/serum3_register_market.rs | 4 +- .../src/instructions/token_register.rs | 4 +- .../instructions/token_register_trustless.rs | 4 +- programs/mango-v4/src/state/bank.rs | 58 ++----------------- .../src/state/mango_account_components.rs | 30 +++++----- programs/mango-v4/src/util.rs | 22 ++++--- 11 files changed, 58 insertions(+), 91 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e30190d8..2a5d75251 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1577,6 +1577,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2 1.0.39", + "quote 1.0.18", + "syn 1.0.95", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -3192,6 +3203,7 @@ dependencies = [ "borsh", "bytemuck", "checked_math", + "derivative", "env_logger 0.9.0", "fixed", "fixed-macro", diff --git a/programs/mango-v4/Cargo.toml b/programs/mango-v4/Cargo.toml index a6cfe6349..ba4779271 100644 --- a/programs/mango-v4/Cargo.toml +++ b/programs/mango-v4/Cargo.toml @@ -28,6 +28,7 @@ bincode = "1.3.3" borsh = { version = "0.9.3", features = ["const-generics"] } bytemuck = "^1.7.2" checked_math = { path = "../../lib/checked_math" } +derivative = "2.2.0" fixed = { version = "=1.11.0", features = ["serde", "borsh"] } # todo: higher versions don't work fixed-macro = "^1.1.1" mango-macro = { path = "../../mango-macro" } diff --git a/programs/mango-v4/src/instructions/account_create.rs b/programs/mango-v4/src/instructions/account_create.rs index 416b02c29..8eb8a1919 100644 --- a/programs/mango-v4/src/instructions/account_create.rs +++ b/programs/mango-v4/src/instructions/account_create.rs @@ -2,7 +2,7 @@ use anchor_lang::prelude::*; use crate::error::*; use crate::state::*; -use crate::util::fill32_from_str; +use crate::util::fill_from_str; #[derive(Accounts)] #[instruction(account_num: u32, token_count: u8, serum3_count: u8, perp_count: u8, perp_oo_count: u8)] @@ -41,7 +41,7 @@ pub fn account_create( account.header_version() ); - account.fixed.name = fill32_from_str(name)?; + account.fixed.name = fill_from_str(&name)?; account.fixed.group = ctx.accounts.group.key(); account.fixed.owner = ctx.accounts.owner.key(); account.fixed.account_num = account_num; diff --git a/programs/mango-v4/src/instructions/account_edit.rs b/programs/mango-v4/src/instructions/account_edit.rs index 0b5bd892f..52596f7d6 100644 --- a/programs/mango-v4/src/instructions/account_edit.rs +++ b/programs/mango-v4/src/instructions/account_edit.rs @@ -1,8 +1,8 @@ -use crate::error::MangoError; use anchor_lang::prelude::*; +use crate::error::MangoError; use crate::state::*; -use crate::util::fill32_from_str; +use crate::util::fill_from_str; #[derive(Accounts)] pub struct AccountEdit<'info> { @@ -34,7 +34,7 @@ pub fn account_edit( // please maintain, and don't remove, makes it easy to reason about which support modification by owner if let Some(name) = name_opt { - account.fixed.name = fill32_from_str(name)?; + account.fixed.name = fill_from_str(&name)?; } // unchanged - diff --git a/programs/mango-v4/src/instructions/perp_create_market.rs b/programs/mango-v4/src/instructions/perp_create_market.rs index 8c0baee5e..df88c99ff 100644 --- a/programs/mango-v4/src/instructions/perp_create_market.rs +++ b/programs/mango-v4/src/instructions/perp_create_market.rs @@ -4,7 +4,7 @@ use fixed::types::I80F48; use crate::error::MangoError; use crate::state::*; -use crate::util::fill16_from_str; +use crate::util::fill_from_str; #[derive(Accounts)] #[instruction(perp_market_index: PerpMarketIndex)] @@ -66,7 +66,7 @@ pub fn perp_create_market( ) -> Result<()> { let mut perp_market = ctx.accounts.perp_market.load_init()?; *perp_market = PerpMarket { - name: fill16_from_str(name)?, + name: fill_from_str(&name)?, group: ctx.accounts.group.key(), oracle: ctx.accounts.oracle.key(), oracle_config, diff --git a/programs/mango-v4/src/instructions/serum3_register_market.rs b/programs/mango-v4/src/instructions/serum3_register_market.rs index 228b8bd97..9ad1dfaa6 100644 --- a/programs/mango-v4/src/instructions/serum3_register_market.rs +++ b/programs/mango-v4/src/instructions/serum3_register_market.rs @@ -3,7 +3,7 @@ use anchor_lang::prelude::*; use crate::error::MangoError; use crate::serum3_cpi::{load_market_state, pubkey_from_u64_array}; use crate::state::*; -use crate::util::fill16_from_str; +use crate::util::fill_from_str; #[derive(Accounts)] pub struct Serum3RegisterMarket<'info> { @@ -67,7 +67,7 @@ pub fn serum3_register_market( let mut serum_market = ctx.accounts.serum_market.load_init()?; *serum_market = Serum3Market { - name: fill16_from_str(name)?, + name: fill_from_str(&name)?, group: ctx.accounts.group.key(), serum_program: ctx.accounts.serum_program.key(), serum_market_external: ctx.accounts.serum_market_external.key(), diff --git a/programs/mango-v4/src/instructions/token_register.rs b/programs/mango-v4/src/instructions/token_register.rs index f2bf50a79..0ea0dc03b 100644 --- a/programs/mango-v4/src/instructions/token_register.rs +++ b/programs/mango-v4/src/instructions/token_register.rs @@ -5,7 +5,7 @@ use fixed_macro::types::I80F48; use crate::error::*; use crate::state::*; -use crate::util::fill16_from_str; +use crate::util::fill_from_str; pub const INDEX_START: I80F48 = I80F48!(1_000_000); @@ -101,7 +101,7 @@ pub fn token_register( let mut bank = ctx.accounts.bank.load_init()?; *bank = Bank { group: ctx.accounts.group.key(), - name: fill16_from_str(name)?, + name: fill_from_str(&name)?, mint: ctx.accounts.mint.key(), vault: ctx.accounts.vault.key(), oracle: ctx.accounts.oracle.key(), diff --git a/programs/mango-v4/src/instructions/token_register_trustless.rs b/programs/mango-v4/src/instructions/token_register_trustless.rs index bee8a648e..9996ba519 100644 --- a/programs/mango-v4/src/instructions/token_register_trustless.rs +++ b/programs/mango-v4/src/instructions/token_register_trustless.rs @@ -5,7 +5,7 @@ use fixed::types::I80F48; use crate::error::*; use crate::instructions::INDEX_START; use crate::state::*; -use crate::util::fill16_from_str; +use crate::util::fill_from_str; const FIRST_BANK_NUM: u32 = 0; @@ -72,7 +72,7 @@ pub fn token_register_trustless( let mut bank = ctx.accounts.bank.load_init()?; *bank = Bank { group: ctx.accounts.group.key(), - name: fill16_from_str(name)?, + name: fill_from_str(&name)?, mint: ctx.accounts.mint.key(), vault: ctx.accounts.vault.key(), oracle: ctx.accounts.oracle.key(), diff --git a/programs/mango-v4/src/state/bank.rs b/programs/mango-v4/src/state/bank.rs index 21c926c51..08433ae20 100644 --- a/programs/mango-v4/src/state/bank.rs +++ b/programs/mango-v4/src/state/bank.rs @@ -1,6 +1,8 @@ use super::{OracleConfig, TokenIndex, TokenPosition}; +use crate::util; use crate::util::checked_math as cm; use anchor_lang::prelude::*; +use derivative::Derivative; use fixed::types::I80F48; use fixed_macro::types::I80F48; use static_assertions::const_assert_eq; @@ -13,11 +15,14 @@ pub const DAY_I80F48: I80F48 = I80F48!(86400); pub const YEAR_I80F48: I80F48 = I80F48!(31536000); pub const MINIMUM_MAX_RATE: I80F48 = I80F48!(0.5); +#[derive(Derivative)] +#[derivative(Debug)] #[account(zero_copy)] pub struct Bank { // ABI: Clients rely on this being at offset 8 pub group: Pubkey, + #[derivative(Debug(format_with = "util::format_zero_terminated_utf8_bytes"))] pub name: [u8; 16], pub mint: Pubkey, @@ -94,6 +99,7 @@ pub struct Bank { pub bank_num: u32, + #[derivative(Debug = "ignore")] pub reserved: [u8; 2560], } const_assert_eq!( @@ -102,58 +108,6 @@ const_assert_eq!( ); const_assert_eq!(size_of::() % 8, 0); -impl std::fmt::Debug for Bank { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Bank") - .field("name", &self.name()) - .field("group", &self.group) - .field("mint", &self.mint) - .field("vault", &self.vault) - .field("oracle", &self.oracle) - .field("oracle_config", &self.oracle_config) - .field("deposit_index", &self.deposit_index) - .field("borrow_index", &self.borrow_index) - .field( - "cached_indexed_total_deposits", - &self.cached_indexed_total_deposits, - ) - .field( - "cached_indexed_total_borrows", - &self.cached_indexed_total_borrows, - ) - .field("indexed_deposits", &self.indexed_deposits) - .field("indexed_borrows", &self.indexed_borrows) - .field("index_last_updated", &self.index_last_updated) - .field("bank_rate_last_updated", &self.bank_rate_last_updated) - .field("avg_utilization", &self.avg_utilization) - .field("util0", &self.util0) - .field("rate0", &self.rate0) - .field("util1", &self.util1) - .field("rate1", &self.rate1) - .field("max_rate", &self.max_rate) - .field("collected_fees_native", &self.collected_fees_native) - .field("loan_origination_fee_rate", &self.loan_origination_fee_rate) - .field("loan_fee_rate", &self.loan_fee_rate) - .field("maint_asset_weight", &self.maint_asset_weight) - .field("init_asset_weight", &self.init_asset_weight) - .field("maint_liab_weight", &self.maint_liab_weight) - .field("init_liab_weight", &self.init_liab_weight) - .field("liquidation_fee", &self.liquidation_fee) - .field("dust", &self.dust) - .field("token_index", &self.token_index) - .field( - "flash_loan_approved_amount", - &self.flash_loan_approved_amount, - ) - .field( - "flash_loan_token_account_initial", - &self.flash_loan_token_account_initial, - ) - .field("reserved", &self.reserved) - .finish() - } -} - impl Bank { pub fn from_existing_bank(existing_bank: &Bank, vault: Pubkey, bank_num: u32) -> Self { Self { diff --git a/programs/mango-v4/src/state/mango_account_components.rs b/programs/mango-v4/src/state/mango_account_components.rs index 6bf34b05c..b1247a0b8 100644 --- a/programs/mango-v4/src/state/mango_account_components.rs +++ b/programs/mango-v4/src/state/mango_account_components.rs @@ -1,5 +1,6 @@ use anchor_lang::prelude::*; use checked_math as cm; +use derivative::Derivative; use fixed::types::I80F48; use static_assertions::const_assert_eq; use std::cmp::Ordering; @@ -10,7 +11,8 @@ use crate::state::*; pub const FREE_ORDER_SLOT: PerpMarketIndex = PerpMarketIndex::MAX; #[zero_copy] -#[derive(AnchorDeserialize, AnchorSerialize, Debug)] +#[derive(AnchorDeserialize, AnchorSerialize, Derivative)] +#[derivative(Debug)] pub struct TokenPosition { // TODO: Why did we have deposits and borrows as two different values // if only one of them was allowed to be != 0 at a time? @@ -26,8 +28,10 @@ pub struct TokenPosition { /// incremented when a market requires this position to stay alive pub in_use_count: u8, + #[derivative(Debug = "ignore")] pub padding: [u8; 5], + #[derivative(Debug = "ignore")] pub reserved: [u8; 40], } @@ -82,7 +86,8 @@ impl TokenPosition { } #[zero_copy] -#[derive(AnchorSerialize, AnchorDeserialize, Debug)] +#[derive(AnchorSerialize, AnchorDeserialize, Derivative)] +#[derivative(Debug)] pub struct Serum3Orders { pub open_orders: Pubkey, @@ -101,8 +106,10 @@ pub struct Serum3Orders { pub base_token_index: TokenIndex, pub quote_token_index: TokenIndex, + #[derivative(Debug = "ignore")] pub padding: [u8; 2], + #[derivative(Debug = "ignore")] pub reserved: [u8; 64], } const_assert_eq!(size_of::(), 32 + 8 * 2 + 2 * 3 + 2 + 64); @@ -137,9 +144,11 @@ impl Default for Serum3Orders { } #[zero_copy] -#[derive(AnchorSerialize, AnchorDeserialize)] +#[derive(AnchorSerialize, AnchorDeserialize, Derivative)] +#[derivative(Debug)] pub struct PerpPositions { pub market_index: PerpMarketIndex, + #[derivative(Debug = "ignore")] pub padding: [u8; 6], /// Active position size, measured in base lots @@ -168,22 +177,9 @@ pub struct PerpPositions { pub taker_base_lots: i64, pub taker_quote_lots: i64, + #[derivative(Debug = "ignore")] pub reserved: [u8; 64], } - -impl std::fmt::Debug for PerpPositions { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("PerpAccount") - .field("market_index", &self.market_index) - .field("base_position_lots", &self.base_position_lots) - .field("quote_position_native", &self.quote_position_native) - .field("bids_base_lots", &self.bids_base_lots) - .field("asks_base_lots", &self.asks_base_lots) - .field("taker_base_lots", &self.taker_base_lots) - .field("taker_quote_lots", &self.taker_quote_lots) - .finish() - } -} const_assert_eq!(size_of::(), 8 + 7 * 8 + 3 * 16 + 64); const_assert_eq!(size_of::() % 8, 0); diff --git a/programs/mango-v4/src/util.rs b/programs/mango-v4/src/util.rs index 33576c618..112ec6719 100644 --- a/programs/mango-v4/src/util.rs +++ b/programs/mango-v4/src/util.rs @@ -20,18 +20,22 @@ macro_rules! checked_math { } pub(crate) use checked_math; -pub fn fill16_from_str(name: String) -> Result<[u8; 16]> { +pub fn fill_from_str(name: &str) -> Result<[u8; N]> { let name_bytes = name.as_bytes(); - require!(name_bytes.len() < 16, MangoError::SomeError); - let mut name_ = [0u8; 16]; + require!(name_bytes.len() < N, MangoError::SomeError); + let mut name_ = [0u8; N]; name_[..name_bytes.len()].copy_from_slice(name_bytes); Ok(name_) } -pub fn fill32_from_str(name: String) -> Result<[u8; 32]> { - let name_bytes = name.as_bytes(); - require!(name_bytes.len() < 32, MangoError::SomeError); - let mut name_ = [0u8; 32]; - name_[..name_bytes.len()].copy_from_slice(name_bytes); - Ok(name_) +pub fn format_zero_terminated_utf8_bytes( + name: &[u8], + fmt: &mut std::fmt::Formatter, +) -> std::result::Result<(), std::fmt::Error> { + fmt.write_str( + std::str::from_utf8(name) + .unwrap() + .trim_matches(char::from(0)), + ) + .into() } From 21815612ae6d377e21075a91de3830941ce9ad19 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Sat, 13 Aug 2022 19:30:35 +0200 Subject: [PATCH 5/7] Let all PDA seeds start with a unique prefix (#166) This is mostly paranoia. Now it's guaranteed that different PDA types have unique seeds. --- .../src/instructions/account_create.rs | 2 +- .../mango-v4/src/instructions/group_create.rs | 2 +- .../src/instructions/perp_create_market.rs | 2 +- .../instructions/serum3_create_open_orders.rs | 2 +- .../instructions/serum3_register_market.rs | 2 +- .../src/instructions/stub_oracle_create.rs | 2 +- .../src/instructions/token_add_bank.rs | 6 +- .../src/instructions/token_register.rs | 6 +- .../instructions/token_register_trustless.rs | 6 +- programs/mango-v4/src/state/bank.rs | 2 +- .../src/state/mango_account_components.rs | 2 +- programs/mango-v4/src/state/serum3_market.rs | 2 +- .../tests/program_test/mango_client.rs | 56 +-- ts/client/src/mango_v4.ts | 320 +++++++++--------- 14 files changed, 202 insertions(+), 210 deletions(-) diff --git a/programs/mango-v4/src/instructions/account_create.rs b/programs/mango-v4/src/instructions/account_create.rs index 8eb8a1919..3da39f06f 100644 --- a/programs/mango-v4/src/instructions/account_create.rs +++ b/programs/mango-v4/src/instructions/account_create.rs @@ -11,7 +11,7 @@ pub struct AccountCreate<'info> { #[account( init, - seeds = [group.key().as_ref(), b"MangoAccount".as_ref(), owner.key().as_ref(), &account_num.to_le_bytes()], + seeds = [b"MangoAccount".as_ref(), group.key().as_ref(), owner.key().as_ref(), &account_num.to_le_bytes()], bump, payer = payer, space = MangoAccount::space(token_count, serum3_count, perp_count, perp_oo_count)?, diff --git a/programs/mango-v4/src/instructions/group_create.rs b/programs/mango-v4/src/instructions/group_create.rs index bdb1a6f80..981db35a8 100644 --- a/programs/mango-v4/src/instructions/group_create.rs +++ b/programs/mango-v4/src/instructions/group_create.rs @@ -22,7 +22,7 @@ pub struct GroupCreate<'info> { #[account( init, - seeds = [group.key().as_ref(), b"InsuranceVault".as_ref()], + seeds = [b"InsuranceVault".as_ref(), group.key().as_ref()], bump, token::authority = group, token::mint = insurance_mint, diff --git a/programs/mango-v4/src/instructions/perp_create_market.rs b/programs/mango-v4/src/instructions/perp_create_market.rs index df88c99ff..d5c76fb16 100644 --- a/programs/mango-v4/src/instructions/perp_create_market.rs +++ b/programs/mango-v4/src/instructions/perp_create_market.rs @@ -21,7 +21,7 @@ pub struct PerpCreateMarket<'info> { #[account( init, - seeds = [group.key().as_ref(), b"PerpMarket".as_ref(), perp_market_index.to_le_bytes().as_ref()], + seeds = [b"PerpMarket".as_ref(), group.key().as_ref(), perp_market_index.to_le_bytes().as_ref()], bump, payer = payer, space = 8 + std::mem::size_of::(), diff --git a/programs/mango-v4/src/instructions/serum3_create_open_orders.rs b/programs/mango-v4/src/instructions/serum3_create_open_orders.rs index b0c4889ef..58473f26c 100644 --- a/programs/mango-v4/src/instructions/serum3_create_open_orders.rs +++ b/programs/mango-v4/src/instructions/serum3_create_open_orders.rs @@ -25,7 +25,7 @@ pub struct Serum3CreateOpenOrders<'info> { // initialized by this instruction via cpi to serum #[account( init, - seeds = [account.key().as_ref(), b"Serum3OO".as_ref(), serum_market.key().as_ref()], + seeds = [b"Serum3OO".as_ref(), account.key().as_ref(), serum_market.key().as_ref()], bump, payer = payer, owner = serum_program.key(), diff --git a/programs/mango-v4/src/instructions/serum3_register_market.rs b/programs/mango-v4/src/instructions/serum3_register_market.rs index 9ad1dfaa6..a2d07b5d1 100644 --- a/programs/mango-v4/src/instructions/serum3_register_market.rs +++ b/programs/mango-v4/src/instructions/serum3_register_market.rs @@ -24,7 +24,7 @@ pub struct Serum3RegisterMarket<'info> { #[account( init, // using the serum_market_external in the seed guards against registering the same market twice - seeds = [group.key().as_ref(), b"Serum3Market".as_ref(), serum_market_external.key().as_ref()], + seeds = [b"Serum3Market".as_ref(), group.key().as_ref(), serum_market_external.key().as_ref()], bump, payer = payer, space = 8 + std::mem::size_of::(), diff --git a/programs/mango-v4/src/instructions/stub_oracle_create.rs b/programs/mango-v4/src/instructions/stub_oracle_create.rs index b05d65a2d..25b928ce4 100644 --- a/programs/mango-v4/src/instructions/stub_oracle_create.rs +++ b/programs/mango-v4/src/instructions/stub_oracle_create.rs @@ -13,7 +13,7 @@ pub struct StubOracleCreate<'info> { #[account( init, - seeds = [group.key().as_ref(), b"StubOracle".as_ref(), mint.key().as_ref()], + seeds = [b"StubOracle".as_ref(), group.key().as_ref(), mint.key().as_ref()], bump, payer = payer, space = 8 + std::mem::size_of::(), diff --git a/programs/mango-v4/src/instructions/token_add_bank.rs b/programs/mango-v4/src/instructions/token_add_bank.rs index 81f3835fe..719a9c554 100644 --- a/programs/mango-v4/src/instructions/token_add_bank.rs +++ b/programs/mango-v4/src/instructions/token_add_bank.rs @@ -25,7 +25,7 @@ pub struct TokenAddBank<'info> { #[account( init, // using the token_index in this seed guards against reusing it - seeds = [group.key().as_ref(), b"Bank".as_ref(), &token_index.to_le_bytes(), &bank_num.to_le_bytes()], + seeds = [b"Bank".as_ref(), group.key().as_ref(), &token_index.to_le_bytes(), &bank_num.to_le_bytes()], bump, payer = payer, space = 8 + std::mem::size_of::(), @@ -34,7 +34,7 @@ pub struct TokenAddBank<'info> { #[account( init, - seeds = [group.key().as_ref(), b"Vault".as_ref(), &token_index.to_le_bytes(), &bank_num.to_le_bytes()], + seeds = [b"Vault".as_ref(), group.key().as_ref(), &token_index.to_le_bytes(), &bank_num.to_le_bytes()], bump, token::authority = group, token::mint = mint, @@ -44,7 +44,7 @@ pub struct TokenAddBank<'info> { #[account( mut, - seeds = [group.key().as_ref(), b"MintInfo".as_ref(), mint.key().as_ref()], + seeds = [b"MintInfo".as_ref(), group.key().as_ref(), mint.key().as_ref()], bump )] pub mint_info: AccountLoader<'info, MintInfo>, diff --git a/programs/mango-v4/src/instructions/token_register.rs b/programs/mango-v4/src/instructions/token_register.rs index 0ea0dc03b..453d37f86 100644 --- a/programs/mango-v4/src/instructions/token_register.rs +++ b/programs/mango-v4/src/instructions/token_register.rs @@ -25,7 +25,7 @@ pub struct TokenRegister<'info> { #[account( init, // using the token_index in this seed guards against reusing it - seeds = [group.key().as_ref(), b"Bank".as_ref(), &token_index.to_le_bytes(), &FIRST_BANK_NUM.to_le_bytes()], + seeds = [b"Bank".as_ref(), group.key().as_ref(), &token_index.to_le_bytes(), &FIRST_BANK_NUM.to_le_bytes()], bump, payer = payer, space = 8 + std::mem::size_of::(), @@ -34,7 +34,7 @@ pub struct TokenRegister<'info> { #[account( init, - seeds = [group.key().as_ref(), b"Vault".as_ref(), &token_index.to_le_bytes(), &FIRST_BANK_NUM.to_le_bytes()], + seeds = [b"Vault".as_ref(), group.key().as_ref(), &token_index.to_le_bytes(), &FIRST_BANK_NUM.to_le_bytes()], bump, token::authority = group, token::mint = mint, @@ -45,7 +45,7 @@ pub struct TokenRegister<'info> { #[account( init, // using the mint in this seed guards against registering the same mint twice - seeds = [group.key().as_ref(), b"MintInfo".as_ref(), mint.key().as_ref()], + seeds = [b"MintInfo".as_ref(), group.key().as_ref(), mint.key().as_ref()], bump, payer = payer, space = 8 + std::mem::size_of::(), diff --git a/programs/mango-v4/src/instructions/token_register_trustless.rs b/programs/mango-v4/src/instructions/token_register_trustless.rs index 9996ba519..3853226f5 100644 --- a/programs/mango-v4/src/instructions/token_register_trustless.rs +++ b/programs/mango-v4/src/instructions/token_register_trustless.rs @@ -23,7 +23,7 @@ pub struct TokenRegisterTrustless<'info> { #[account( init, // using the token_index in this seed guards against reusing it - seeds = [group.key().as_ref(), b"Bank".as_ref(), &token_index.to_le_bytes(), &FIRST_BANK_NUM.to_le_bytes()], + seeds = [b"Bank".as_ref(), group.key().as_ref(), &token_index.to_le_bytes(), &FIRST_BANK_NUM.to_le_bytes()], bump, payer = payer, space = 8 + std::mem::size_of::(), @@ -32,7 +32,7 @@ pub struct TokenRegisterTrustless<'info> { #[account( init, - seeds = [group.key().as_ref(), b"Vault".as_ref(), &token_index.to_le_bytes(), &FIRST_BANK_NUM.to_le_bytes()], + seeds = [b"Vault".as_ref(), group.key().as_ref(), &token_index.to_le_bytes(), &FIRST_BANK_NUM.to_le_bytes()], bump, token::authority = group, token::mint = mint, @@ -43,7 +43,7 @@ pub struct TokenRegisterTrustless<'info> { #[account( init, // using the mint in this seed guards against registering the same mint twice - seeds = [group.key().as_ref(), b"MintInfo".as_ref(), mint.key().as_ref()], + seeds = [b"MintInfo".as_ref(), group.key().as_ref(), mint.key().as_ref()], bump, payer = payer, space = 8 + std::mem::size_of::(), diff --git a/programs/mango-v4/src/state/bank.rs b/programs/mango-v4/src/state/bank.rs index 08433ae20..cb8b9ddb1 100644 --- a/programs/mango-v4/src/state/bank.rs +++ b/programs/mango-v4/src/state/bank.rs @@ -489,8 +489,8 @@ impl Bank { macro_rules! bank_seeds { ( $bank:expr ) => { &[ - $bank.group.as_ref(), b"Bank".as_ref(), + $bank.group.as_ref(), $bank.token_index.to_le_bytes(), &bank.bank_num.to_le_bytes(), &[$bank.bump], diff --git a/programs/mango-v4/src/state/mango_account_components.rs b/programs/mango-v4/src/state/mango_account_components.rs index b1247a0b8..56fefb304 100644 --- a/programs/mango-v4/src/state/mango_account_components.rs +++ b/programs/mango-v4/src/state/mango_account_components.rs @@ -354,8 +354,8 @@ const_assert_eq!(size_of::() % 8, 0); macro_rules! account_seeds { ( $account:expr ) => { &[ - $account.group.as_ref(), b"MangoAccount".as_ref(), + $account.group.as_ref(), $account.owner.as_ref(), &$account.account_num.to_le_bytes(), &[$account.bump], diff --git a/programs/mango-v4/src/state/serum3_market.rs b/programs/mango-v4/src/state/serum3_market.rs index 8d066fb61..1f97aaf4f 100644 --- a/programs/mango-v4/src/state/serum3_market.rs +++ b/programs/mango-v4/src/state/serum3_market.rs @@ -48,8 +48,8 @@ impl Serum3Market { macro_rules! serum_market_seeds { ( $acc:expr ) => { &[ - $acc.group.as_ref(), b"Serum3Market".as_ref(), + $acc.group.as_ref(), $acc.serum_market_external.as_ref(), &[$acc.bump], ] diff --git a/programs/mango-v4/tests/program_test/mango_client.rs b/programs/mango-v4/tests/program_test/mango_client.rs index 367d470b1..949499b43 100644 --- a/programs/mango-v4/tests/program_test/mango_client.rs +++ b/programs/mango-v4/tests/program_test/mango_client.rs @@ -128,8 +128,8 @@ async fn get_mint_info_by_mint( ) -> MintInfo { let mint_info_pk = Pubkey::find_program_address( &[ - account.fixed.group.as_ref(), b"MintInfo".as_ref(), + account.fixed.group.as_ref(), mint.as_ref(), ], &mango_v4::id(), @@ -145,8 +145,8 @@ async fn get_mint_info_by_token_index( ) -> MintInfo { let bank_pk = Pubkey::find_program_address( &[ - account.fixed.group.as_ref(), b"Bank".as_ref(), + account.fixed.group.as_ref(), &token_index.to_le_bytes(), &0u32.to_le_bytes(), ], @@ -160,8 +160,8 @@ async fn get_mint_info_by_token_index( fn get_perp_market_address_by_index(group: Pubkey, perp_market_index: PerpMarketIndex) -> Pubkey { Pubkey::find_program_address( &[ - group.as_ref(), b"PerpMarket".as_ref(), + group.as_ref(), &perp_market_index.to_le_bytes(), ], &mango_v4::id(), @@ -466,8 +466,8 @@ impl<'keypair> ClientInstruction for TokenWithdrawInstruction<'keypair> { .unwrap(); let mint_info = Pubkey::find_program_address( &[ - account.fixed.group.as_ref(), b"MintInfo".as_ref(), + account.fixed.group.as_ref(), token_account.mint.as_ref(), ], &program_id, @@ -534,8 +534,8 @@ impl ClientInstruction for TokenDepositInstruction { .unwrap(); let mint_info = Pubkey::find_program_address( &[ - account.fixed.group.as_ref(), b"MintInfo".as_ref(), + account.fixed.group.as_ref(), token_account.mint.as_ref(), ], &program_id, @@ -633,8 +633,8 @@ impl<'keypair> ClientInstruction for TokenRegisterInstruction<'keypair> { let bank = Pubkey::find_program_address( &[ - self.group.as_ref(), b"Bank".as_ref(), + self.group.as_ref(), &self.token_index.to_le_bytes(), &0u32.to_le_bytes(), ], @@ -643,8 +643,8 @@ impl<'keypair> ClientInstruction for TokenRegisterInstruction<'keypair> { .0; let vault = Pubkey::find_program_address( &[ - self.group.as_ref(), b"Vault".as_ref(), + self.group.as_ref(), &self.token_index.to_le_bytes(), &0u32.to_le_bytes(), ], @@ -653,8 +653,8 @@ impl<'keypair> ClientInstruction for TokenRegisterInstruction<'keypair> { .0; let mint_info = Pubkey::find_program_address( &[ - self.group.as_ref(), b"MintInfo".as_ref(), + self.group.as_ref(), self.mint.as_ref(), ], &program_id, @@ -663,8 +663,8 @@ impl<'keypair> ClientInstruction for TokenRegisterInstruction<'keypair> { // TODO: remove copy pasta of pda derivation, use reference let oracle = Pubkey::find_program_address( &[ - self.group.as_ref(), b"StubOracle".as_ref(), + self.group.as_ref(), self.mint.as_ref(), ], &program_id, @@ -718,8 +718,8 @@ impl<'keypair> ClientInstruction for TokenAddBankInstruction<'keypair> { let existing_bank = Pubkey::find_program_address( &[ - self.group.as_ref(), b"Bank".as_ref(), + self.group.as_ref(), &self.token_index.to_le_bytes(), &0u32.to_le_bytes(), ], @@ -728,8 +728,8 @@ impl<'keypair> ClientInstruction for TokenAddBankInstruction<'keypair> { .0; let bank = Pubkey::find_program_address( &[ - self.group.as_ref(), b"Bank".as_ref(), + self.group.as_ref(), &self.token_index.to_le_bytes(), &self.bank_num.to_le_bytes(), ], @@ -738,8 +738,8 @@ impl<'keypair> ClientInstruction for TokenAddBankInstruction<'keypair> { .0; let vault = Pubkey::find_program_address( &[ - self.group.as_ref(), b"Vault".as_ref(), + self.group.as_ref(), &self.token_index.to_le_bytes(), &self.bank_num.to_le_bytes(), ], @@ -751,7 +751,7 @@ impl<'keypair> ClientInstruction for TokenAddBankInstruction<'keypair> { let mint = existing_bank_data.mint; let mint_info = Pubkey::find_program_address( - &[self.group.as_ref(), b"MintInfo".as_ref(), mint.as_ref()], + &[b"MintInfo".as_ref(), self.group.as_ref(), mint.as_ref()], &program_id, ) .0; @@ -869,8 +869,8 @@ impl<'keypair> ClientInstruction for StubOracleSetInstruction<'keypair> { // TODO: remove copy pasta of pda derivation, use reference let oracle = Pubkey::find_program_address( &[ - self.group.as_ref(), b"StubOracle".as_ref(), + self.group.as_ref(), self.mint.as_ref(), ], &program_id, @@ -915,8 +915,8 @@ impl<'keypair> ClientInstruction for StubOracleCreate<'keypair> { let oracle = Pubkey::find_program_address( &[ - self.group.as_ref(), b"StubOracle".as_ref(), + self.group.as_ref(), self.mint.as_ref(), ], &program_id, @@ -961,8 +961,8 @@ impl<'keypair> ClientInstruction for StubOracleCloseInstruction<'keypair> { let oracle = Pubkey::find_program_address( &[ - self.group.as_ref(), b"StubOracle".as_ref(), + self.group.as_ref(), self.mint.as_ref(), ], &program_id, @@ -1017,7 +1017,7 @@ impl<'keypair> ClientInstruction for GroupCreateInstruction<'keypair> { .0; let insurance_vault = Pubkey::find_program_address( - &[group.as_ref(), b"InsuranceVault".as_ref()], + &[b"InsuranceVault".as_ref(), group.as_ref()], &program_id, ) .0; @@ -1059,7 +1059,7 @@ impl<'keypair> ClientInstruction for GroupCloseInstruction<'keypair> { let instruction = Self::Instruction {}; let insurance_vault = Pubkey::find_program_address( - &[self.group.as_ref(), b"InsuranceVault".as_ref()], + &[b"InsuranceVault".as_ref(), self.group.as_ref()], &program_id, ) .0; @@ -1111,8 +1111,8 @@ impl<'keypair> ClientInstruction for AccountCreateInstruction<'keypair> { let account = Pubkey::find_program_address( &[ - self.group.as_ref(), b"MangoAccount".as_ref(), + self.group.as_ref(), self.owner.pubkey().as_ref(), &self.account_num.to_le_bytes(), ], @@ -1165,8 +1165,8 @@ impl<'keypair> ClientInstruction for AccountExpandInstruction<'keypair> { let account = Pubkey::find_program_address( &[ - self.group.as_ref(), b"MangoAccount".as_ref(), + self.group.as_ref(), self.owner.pubkey().as_ref(), &self.account_num.to_le_bytes(), ], @@ -1214,8 +1214,8 @@ impl<'keypair> ClientInstruction for AccountEditInstruction<'keypair> { let account = Pubkey::find_program_address( &[ - self.group.as_ref(), b"MangoAccount".as_ref(), + self.group.as_ref(), self.owner.pubkey().as_ref(), &self.account_num.to_le_bytes(), ], @@ -1301,8 +1301,8 @@ impl<'keypair> ClientInstruction for Serum3RegisterMarketInstruction<'keypair> { let serum_market = Pubkey::find_program_address( &[ - self.group.as_ref(), b"Serum3Market".as_ref(), + self.group.as_ref(), self.serum_market_external.as_ref(), ], &program_id, @@ -1349,8 +1349,8 @@ impl<'keypair> ClientInstruction for Serum3DeregisterMarketInstruction<'keypair> let serum_market = Pubkey::find_program_address( &[ - self.group.as_ref(), b"Serum3Market".as_ref(), + self.group.as_ref(), self.serum_market_external.as_ref(), ], &program_id, @@ -1395,8 +1395,8 @@ impl<'keypair> ClientInstruction for Serum3CreateOpenOrdersInstruction<'keypair> let serum_market: Serum3Market = account_loader.load(&self.serum_market).await.unwrap(); let open_orders = Pubkey::find_program_address( &[ - self.account.as_ref(), b"Serum3OO".as_ref(), + self.account.as_ref(), self.serum_market.as_ref(), ], &program_id, @@ -1446,8 +1446,8 @@ impl<'keypair> ClientInstruction for Serum3CloseOpenOrdersInstruction<'keypair> let serum_market: Serum3Market = account_loader.load(&self.serum_market).await.unwrap(); let open_orders = Pubkey::find_program_address( &[ - self.account.as_ref(), b"Serum3OO".as_ref(), + self.account.as_ref(), self.serum_market.as_ref(), ], &program_id, @@ -1996,8 +1996,8 @@ impl<'keypair> ClientInstruction for LiqTokenBankruptcyInstruction<'keypair> { let quote_mint_info = Pubkey::find_program_address( &[ - liqee.fixed.group.as_ref(), b"MintInfo".as_ref(), + liqee.fixed.group.as_ref(), group.insurance_mint.as_ref(), ], &program_id, @@ -2006,7 +2006,7 @@ impl<'keypair> ClientInstruction for LiqTokenBankruptcyInstruction<'keypair> { let quote_mint_info: MintInfo = account_loader.load("e_mint_info).await.unwrap(); let insurance_vault = Pubkey::find_program_address( - &[group_key.as_ref(), b"InsuranceVault".as_ref()], + &[b"InsuranceVault".as_ref(), group_key.as_ref()], &program_id, ) .0; @@ -2097,8 +2097,8 @@ impl<'keypair> ClientInstruction for PerpCreateMarketInstruction<'keypair> { let perp_market = Pubkey::find_program_address( &[ - self.group.as_ref(), b"PerpMarket".as_ref(), + self.group.as_ref(), self.perp_market_index.to_le_bytes().as_ref(), ], &program_id, diff --git a/ts/client/src/mango_v4.ts b/ts/client/src/mango_v4.ts index 145f24cad..d048e276a 100644 --- a/ts/client/src/mango_v4.ts +++ b/ts/client/src/mango_v4.ts @@ -45,15 +45,15 @@ export type MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "InsuranceVault" + }, + { + "kind": "account", + "type": "publicKey", + "path": "group" } ] } @@ -174,16 +174,16 @@ export type MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "Bank" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "arg", "type": "u16", @@ -203,16 +203,16 @@ export type MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "Vault" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "arg", "type": "u16", @@ -232,16 +232,16 @@ export type MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "MintInfo" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "account", "type": "publicKey", @@ -352,16 +352,16 @@ export type MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "Bank" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "arg", "type": "u16", @@ -381,16 +381,16 @@ export type MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "Vault" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "arg", "type": "u16", @@ -410,16 +410,16 @@ export type MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "MintInfo" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "account", "type": "publicKey", @@ -591,16 +591,16 @@ export type MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "Bank" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "arg", "type": "u16", @@ -620,16 +620,16 @@ export type MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "Vault" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "arg", "type": "u16", @@ -649,16 +649,16 @@ export type MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "MintInfo" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "account", "type": "publicKey", @@ -781,16 +781,16 @@ export type MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "MangoAccount" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "account", "type": "publicKey", @@ -974,16 +974,16 @@ export type MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "StubOracle" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "account", "type": "publicKey", @@ -1269,16 +1269,16 @@ export type MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "Serum3Market" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "account", "type": "publicKey", @@ -1389,16 +1389,16 @@ export type MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "account" - }, { "kind": "const", "type": "string", "value": "Serum3OO" }, + { + "kind": "account", + "type": "publicKey", + "path": "account" + }, { "kind": "account", "type": "publicKey", @@ -2049,16 +2049,16 @@ export type MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "PerpMarket" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "arg", "type": "u16", @@ -4011,18 +4011,14 @@ export type MangoV4 = { } }, { - "name": "baseEntryLots", + "name": "quoteEntryNative", "docs": [ - "Tracks what the position is to calculate average entry & break even price" + "Tracks what the position is to calculate average entry & break even price" ], "type": "i64" }, { - "name": "quoteEntryNative", - "type": "i64" - }, - { - "name": "quoteExitNative", + "name": "quoteRunningNative", "type": "i64" }, { @@ -5089,15 +5085,15 @@ export const IDL: MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "InsuranceVault" + }, + { + "kind": "account", + "type": "publicKey", + "path": "group" } ] } @@ -5218,16 +5214,16 @@ export const IDL: MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "Bank" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "arg", "type": "u16", @@ -5247,16 +5243,16 @@ export const IDL: MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "Vault" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "arg", "type": "u16", @@ -5276,16 +5272,16 @@ export const IDL: MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "MintInfo" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "account", "type": "publicKey", @@ -5396,16 +5392,16 @@ export const IDL: MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "Bank" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "arg", "type": "u16", @@ -5425,16 +5421,16 @@ export const IDL: MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "Vault" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "arg", "type": "u16", @@ -5454,16 +5450,16 @@ export const IDL: MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "MintInfo" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "account", "type": "publicKey", @@ -5635,16 +5631,16 @@ export const IDL: MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "Bank" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "arg", "type": "u16", @@ -5664,16 +5660,16 @@ export const IDL: MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "Vault" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "arg", "type": "u16", @@ -5693,16 +5689,16 @@ export const IDL: MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "MintInfo" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "account", "type": "publicKey", @@ -5825,16 +5821,16 @@ export const IDL: MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "MangoAccount" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "account", "type": "publicKey", @@ -6018,16 +6014,16 @@ export const IDL: MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "StubOracle" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "account", "type": "publicKey", @@ -6313,16 +6309,16 @@ export const IDL: MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "Serum3Market" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "account", "type": "publicKey", @@ -6433,16 +6429,16 @@ export const IDL: MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "account" - }, { "kind": "const", "type": "string", "value": "Serum3OO" }, + { + "kind": "account", + "type": "publicKey", + "path": "account" + }, { "kind": "account", "type": "publicKey", @@ -7093,16 +7089,16 @@ export const IDL: MangoV4 = { "isSigner": false, "pda": { "seeds": [ - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, { "kind": "const", "type": "string", "value": "PerpMarket" }, + { + "kind": "account", + "type": "publicKey", + "path": "group" + }, { "kind": "arg", "type": "u16", @@ -9055,18 +9051,14 @@ export const IDL: MangoV4 = { } }, { - "name": "baseEntryLots", + "name": "quoteEntryNative", "docs": [ - "Tracks what the position is to calculate average entry & break even price" + "Tracks what the position is to calculate average entry & break even price" ], "type": "i64" }, { - "name": "quoteEntryNative", - "type": "i64" - }, - { - "name": "quoteExitNative", + "name": "quoteRunningNative", "type": "i64" }, { From 41e42da620351c38853bd17ac3fa8ee458249f74 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sat, 13 Aug 2022 19:36:09 +0200 Subject: [PATCH 6/7] debug banks helper script Signed-off-by: microwavedcola1 --- ts/client/src/accounts/bank.ts | 2 + ts/client/src/client.ts | 16 ++- ts/client/src/debug-scripts/mb-debug-banks.ts | 116 ++++++++++++++++++ ts/client/src/scripts/example1-user.ts | 9 +- .../src/scripts/mb-example1-close-account.ts | 10 +- 5 files changed, 146 insertions(+), 7 deletions(-) create mode 100644 ts/client/src/debug-scripts/mb-debug-banks.ts diff --git a/ts/client/src/accounts/bank.ts b/ts/client/src/accounts/bank.ts index 0637e8992..db197f2be 100644 --- a/ts/client/src/accounts/bank.ts +++ b/ts/client/src/accounts/bank.ts @@ -26,6 +26,7 @@ export class Bank { public util0: I80F48; public util1: I80F48; public price: I80F48; + public collectedFeesNative: I80F48; public loanFeeRate: I80F48; public loanOriginationFeeRate: I80F48; public initAssetWeight: I80F48; @@ -166,6 +167,7 @@ export class Bank { this.rate0 = I80F48.from(rate0); this.util1 = I80F48.from(util1); this.rate1 = I80F48.from(rate1); + this.collectedFeesNative = I80F48.from(collectedFeesNative); this.loanFeeRate = I80F48.from(loanFeeRate); this.loanOriginationFeeRate = I80F48.from(loanOriginationFeeRate); this.maintAssetWeight = I80F48.from(maintAssetWeight); diff --git a/ts/client/src/client.ts b/ts/client/src/client.ts index ba3288c27..d71a673ec 100644 --- a/ts/client/src/client.ts +++ b/ts/client/src/client.ts @@ -15,7 +15,6 @@ import { AccountMeta, Cluster, Keypair, - LAMPORTS_PER_SOL, MemcmpFilter, PublicKey, Signer, @@ -596,6 +595,21 @@ export class MangoClient { }); } + public async getAllMangoAccounts(group: Group): Promise { + return ( + await this.program.account.mangoAccount.all([ + { + memcmp: { + bytes: group.publicKey.toBase58(), + offset: 8, + }, + }, + ]) + ).map((pa) => { + return MangoAccount.from(pa.publicKey, pa.account); + }); + } + public async closeMangoAccount( group: Group, mangoAccount: MangoAccount, diff --git a/ts/client/src/debug-scripts/mb-debug-banks.ts b/ts/client/src/debug-scripts/mb-debug-banks.ts new file mode 100644 index 000000000..234577921 --- /dev/null +++ b/ts/client/src/debug-scripts/mb-debug-banks.ts @@ -0,0 +1,116 @@ +import { AnchorProvider, Wallet } from '@project-serum/anchor'; +import { coder } from '@project-serum/anchor/dist/cjs/spl/token'; +import { Connection, Keypair } from '@solana/web3.js'; +import fs from 'fs'; +import { ZERO_I80F48 } from '../accounts/I80F48'; +import { MangoClient } from '../client'; +import { MANGO_V4_ID } from '../constants'; + +async function main() { + const options = AnchorProvider.defaultOptions(); + const connection = new Connection(process.env.MB_CLUSTER_URL!, options); + + const admin = Keypair.fromSecretKey( + Buffer.from( + JSON.parse(fs.readFileSync(process.env.MB_PAYER_KEYPAIR!, 'utf-8')), + ), + ); + + const adminWallet = new Wallet(admin); + const adminProvider = new AnchorProvider(connection, adminWallet, options); + const client = MangoClient.connect( + adminProvider, + 'mainnet-beta', + MANGO_V4_ID['mainnet-beta'], + ); + + const group = await client.getGroupForCreator(admin.publicKey, 0); + console.log(`Group ${group.publicKey.toBase58()}`); + + const banks = await client.getBanksForGroup(group); + const banksMapUsingTokenIndex = new Map( + banks.map((bank) => { + (bank as any).indexedDepositsByMangoAccounts = ZERO_I80F48; + (bank as any).indexedBorrowsByMangoAccounts = ZERO_I80F48; + return [bank.tokenIndex, bank]; + }), + ); + + const mangoAccounts = await client.getAllMangoAccounts(group); + mangoAccounts.forEach((mangoAccount) => + console.log( + `MangoAccount pk - ${mangoAccount.publicKey}, owner - ${mangoAccount.owner}`, + ), + ); + mangoAccounts.map((mangoAccount) => + mangoAccount.tokensActive().forEach((token) => { + const bank = banksMapUsingTokenIndex.get(token.tokenIndex); + if (token.indexedPosition.isPos()) { + (bank as any).indexedDepositsByMangoAccounts = ( + bank as any + ).indexedDepositsByMangoAccounts.add( + token.indexedPosition.mul( + banksMapUsingTokenIndex.get(token.tokenIndex).depositIndex, + ), + ); + } + if (token.indexedPosition.isNeg()) { + (bank as any).indexedBorrowsByMangoAccounts = ( + bank as any + ).indexedBorrowsByMangoAccounts.add( + token.indexedPosition + .abs() + .mul(banksMapUsingTokenIndex.get(token.tokenIndex).borrowIndex), + ); + } + }), + ); + + for (const bank of await Array.from(banksMapUsingTokenIndex.values()).sort( + (a, b) => a.tokenIndex - b.tokenIndex, + )) { + let res = `${bank.name}`; + res = + res + + `\n ${'collectedFeesNative'.padEnd(40)} ${bank.collectedFeesNative}` + + `\n ${'deposits'.padEnd(40)} ${bank.indexedDeposits.mul( + bank.depositIndex, + )}` + + `\n ${'deposits (sum over all mango accounts)'.padEnd(40)} ${ + (bank as any).indexedDepositsByMangoAccounts + }` + + `\n ${'cachedIndexedTotalDeposits'.padEnd(40)} ${( + bank as any + ).cachedIndexedTotalDeposits.mul(bank.depositIndex)}` + + `\n ${'indexedBorrows'.padEnd(40)} ${bank.indexedBorrows.mul( + bank.borrowIndex, + )}` + + `\n ${'borrows (sum over all mango accounts)'.padEnd(40)} ${ + (bank as any).indexedBorrowsByMangoAccounts + }` + + `\n ${'cachedIndexedTotalBorrows'.padEnd(40)} ${( + bank as any + ).cachedIndexedTotalBorrows.mul(bank.borrowIndex)}` + + `\n ${'avgUtilization'.padEnd(40)} ${bank.avgUtilization}` + + `\n ${'depositRate'.padEnd(40)} ${bank.getDepositRate()}` + + `\n ${'borrowRate'.padEnd(40)} ${bank.getBorrowRate()}` + + `\n ${'vault'.padEnd(40)} ${coder() + .accounts.decode( + 'token', + await ( + await client.program.provider.connection.getAccountInfo(bank.vault) + ).data, + ) + .amount.toNumber()}`; + + console.log(`${res}`); + } + + process.exit(); +} + +try { + main(); +} catch (error) { + console.log(error); +} diff --git a/ts/client/src/scripts/example1-user.ts b/ts/client/src/scripts/example1-user.ts index 93e39b12d..a2e750689 100644 --- a/ts/client/src/scripts/example1-user.ts +++ b/ts/client/src/scripts/example1-user.ts @@ -10,6 +10,7 @@ import { } from '../accounts/serum3'; import { MangoClient } from '../client'; import { MANGO_V4_ID } from '../constants'; +import { toUiDecimalsForQuote } from '../utils'; // // An example for users based on high level api i.e. the client @@ -240,11 +241,15 @@ async function main() { ); console.log( '...mangoAccount.getAssetsVal() ' + - toUiDecimalsForQuote(mangoAccount.getAssetsVal().toNumber()), + toUiDecimalsForQuote( + mangoAccount.getAssetsVal(HealthType.init).toNumber(), + ), ); console.log( '...mangoAccount.getLiabsVal() ' + - toUiDecimalsForQuote(mangoAccount.getLiabsVal().toNumber()), + toUiDecimalsForQuote( + mangoAccount.getLiabsVal(HealthType.init).toNumber(), + ), ); console.log( '...mangoAccount.getMaxWithdrawWithBorrowForToken(group, "SOL") ' + diff --git a/ts/client/src/scripts/mb-example1-close-account.ts b/ts/client/src/scripts/mb-example1-close-account.ts index ed9f54c4d..f1f165916 100644 --- a/ts/client/src/scripts/mb-example1-close-account.ts +++ b/ts/client/src/scripts/mb-example1-close-account.ts @@ -3,6 +3,7 @@ import { Connection, Keypair } from '@solana/web3.js'; import fs from 'fs'; import { Serum3Side } from '../accounts/serum3'; import { MangoClient } from '../client'; +import { MANGO_V4_ID } from '../constants'; // // (untested?) script which closes a mango account cleanly, first closes all positions, withdraws all tokens and then closes it @@ -14,14 +15,15 @@ async function main() { // user const user = Keypair.fromSecretKey( Buffer.from( - JSON.parse(fs.readFileSync(process.env.MB_PAYER_KEYPAIR!, 'utf-8')), + JSON.parse(fs.readFileSync(process.env.USER_KEYPAIR!, 'utf-8')), ), ); const userWallet = new Wallet(user); const userProvider = new AnchorProvider(connection, userWallet, options); - const client = await MangoClient.connectForGroupName( + const client = await MangoClient.connect( userProvider, - 'mainnet-beta.microwavedcola' /* Use ids json instead of getProgramAccounts */, + 'mainnet-beta', + MANGO_V4_ID['mainnet-beta'], ); console.log(`User ${userWallet.publicKey.toBase58()}`); @@ -34,7 +36,7 @@ async function main() { console.log(`Admin ${admin.publicKey.toBase58()}`); // fetch group - const group = await client.getGroupForCreator(admin.publicKey); + const group = await client.getGroupForCreator(admin.publicKey, 0); console.log(`Found group ${group.publicKey.toBase58()}`); // account From ccba4ee597e96624017c97e52285617089ce6a5d Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Sat, 13 Aug 2022 19:54:58 +0200 Subject: [PATCH 7/7] Cleanups and bugfixes from the audit (#163) * AccountExpand: cleanups from audit * Group instructions: cleanups from audit * AccountClose: cleanups from audit * TokenAddBank: Audit fixes, including significant bugs Must not take collected_fees and bump from the existing bank. * Instruction comment updates * GroupEdit: Add version/testing flag changes Ported from mc/vanity --- .../src/instructions/account_close.rs | 27 +++--- .../src/instructions/account_expand.rs | 10 +- .../mango-v4/src/instructions/group_close.rs | 4 +- .../mango-v4/src/instructions/group_create.rs | 2 +- .../mango-v4/src/instructions/group_edit.rs | 27 +++++- .../src/instructions/token_add_bank.rs | 14 +-- .../src/instructions/token_deposit.rs | 3 - .../mango-v4/src/instructions/token_edit.rs | 4 + .../src/instructions/token_register.rs | 2 - .../token_update_index_and_rate.rs | 7 ++ programs/mango-v4/src/lib.rs | 14 ++- programs/mango-v4/src/state/bank.rs | 30 ++++-- programs/mango-v4/src/state/mango_account.rs | 10 +- ts/client/src/client.ts | 13 ++- ts/client/src/mango_v4.ts | 92 +++++++++---------- ts/client/src/scripts/example1-admin.ts | 2 + ts/client/src/scripts/mb-example1-admin.ts | 2 +- 17 files changed, 148 insertions(+), 115 deletions(-) diff --git a/programs/mango-v4/src/instructions/account_close.rs b/programs/mango-v4/src/instructions/account_close.rs index da9b01b58..9f0795f0d 100644 --- a/programs/mango-v4/src/instructions/account_close.rs +++ b/programs/mango-v4/src/instructions/account_close.rs @@ -27,22 +27,19 @@ pub struct AccountClose<'info> { pub fn account_close(ctx: Context) -> Result<()> { let group = ctx.accounts.group.load()?; - { - let account = ctx.accounts.account.load_mut()?; + let account = ctx.accounts.account.load_mut()?; - // don't perform checks if group is just testing - if group.testing == 0 { - require!(!account.fixed.being_liquidated(), MangoError::SomeError); - require_eq!(account.fixed.delegate, Pubkey::default()); - for ele in account.token_iter() { - require_eq!(ele.is_active(), false); - } - for ele in account.serum3_iter() { - require_eq!(ele.is_active(), false); - } - for ele in account.perp_iter() { - require_eq!(ele.is_active(), false); - } + // don't perform checks if group is just testing + if !group.is_testing() { + require!(!account.fixed.being_liquidated(), MangoError::SomeError); + for ele in account.token_iter() { + require_eq!(ele.is_active(), false); + } + for ele in account.serum3_iter() { + require_eq!(ele.is_active(), false); + } + for ele in account.perp_iter() { + require_eq!(ele.is_active(), false); } } diff --git a/programs/mango-v4/src/instructions/account_expand.rs b/programs/mango-v4/src/instructions/account_expand.rs index 244ddca05..8f0397d12 100644 --- a/programs/mango-v4/src/instructions/account_expand.rs +++ b/programs/mango-v4/src/instructions/account_expand.rs @@ -1,6 +1,7 @@ use anchor_lang::prelude::*; use crate::state::*; +use crate::util::checked_math as cm; #[derive(Accounts)] pub struct AccountExpand<'info> { @@ -32,6 +33,7 @@ pub fn account_expand( let realloc_account = ctx.accounts.account.as_ref(); let old_space = realloc_account.data_len(); + let old_lamports = realloc_account.lamports(); require_gt!(new_space, old_space); @@ -44,13 +46,11 @@ pub fn account_expand( to: realloc_account.clone(), }, ), - new_rent_minimum - .checked_sub(realloc_account.lamports()) - .unwrap(), + cm!(new_rent_minimum - old_lamports), )?; - // realloc - realloc_account.realloc(new_space, true)?; + // realloc: it's safe to not re-zero-init since we never shrink accounts + realloc_account.realloc(new_space, false)?; // expand dynamic content, e.g. to grow token positions, we need to slide serum3orders further later, and so on.... let mut account = ctx.accounts.account.load_mut()?; diff --git a/programs/mango-v4/src/instructions/group_close.rs b/programs/mango-v4/src/instructions/group_close.rs index 0df176840..a97b347b4 100644 --- a/programs/mango-v4/src/instructions/group_close.rs +++ b/programs/mango-v4/src/instructions/group_close.rs @@ -26,9 +26,7 @@ pub struct GroupClose<'info> { } pub fn group_close(ctx: Context) -> Result<()> { - // TODO: checks - - // close insurance vault + // close insurance vault (must be empty) let group = ctx.accounts.group.load()?; let group_seeds = group_seeds!(group); let cpi_accounts = CloseAccount { diff --git a/programs/mango-v4/src/instructions/group_create.rs b/programs/mango-v4/src/instructions/group_create.rs index 981db35a8..40f37a3ce 100644 --- a/programs/mango-v4/src/instructions/group_create.rs +++ b/programs/mango-v4/src/instructions/group_create.rs @@ -46,12 +46,12 @@ pub fn group_create( ) -> Result<()> { let mut group = ctx.accounts.group.load_init()?; group.creator = ctx.accounts.creator.key(); + group.group_num = group_num; group.admin = ctx.accounts.creator.key(); group.fast_listing_admin = Pubkey::default(); group.insurance_vault = ctx.accounts.insurance_vault.key(); group.insurance_mint = ctx.accounts.insurance_mint.key(); group.bump = *ctx.bumps.get("group").ok_or(MangoError::SomeError)?; - group.group_num = group_num; group.testing = testing; group.version = version; Ok(()) diff --git a/programs/mango-v4/src/instructions/group_edit.rs b/programs/mango-v4/src/instructions/group_edit.rs index 8d8b9822d..425b46f4a 100644 --- a/programs/mango-v4/src/instructions/group_edit.rs +++ b/programs/mango-v4/src/instructions/group_edit.rs @@ -13,14 +13,31 @@ pub struct GroupEdit<'info> { } // use case - transfer group ownership to governance, where -// new_admin and new_fast_listing_admin are PDAs +// admin and fast_listing_admin are PDAs pub fn group_edit( ctx: Context, - new_admin: Pubkey, - new_fast_listing_admin: Pubkey, + admin_opt: Option, + fast_listing_admin_opt: Option, + testing_opt: Option, + version_opt: Option, ) -> Result<()> { let mut group = ctx.accounts.group.load_mut()?; - group.admin = new_admin; - group.fast_listing_admin = new_fast_listing_admin; + + if let Some(admin) = admin_opt { + group.admin = admin; + } + + if let Some(fast_listing_admin) = fast_listing_admin_opt { + group.fast_listing_admin = fast_listing_admin; + } + + if let Some(testing) = testing_opt { + group.testing = testing; + } + + if let Some(version) = version_opt { + group.version = version; + } + Ok(()) } diff --git a/programs/mango-v4/src/instructions/token_add_bank.rs b/programs/mango-v4/src/instructions/token_add_bank.rs index 719a9c554..87d51d952 100644 --- a/programs/mango-v4/src/instructions/token_add_bank.rs +++ b/programs/mango-v4/src/instructions/token_add_bank.rs @@ -1,6 +1,7 @@ use anchor_lang::prelude::*; use anchor_spl::token::{Mint, Token, TokenAccount}; +use crate::error::*; use crate::state::*; #[derive(Accounts)] @@ -44,10 +45,12 @@ pub struct TokenAddBank<'info> { #[account( mut, - seeds = [b"MintInfo".as_ref(), group.key().as_ref(), mint.key().as_ref()], - bump + constraint = mint_info.load()?.token_index == token_index, + has_one = group, + has_one = mint, )] pub mint_info: AccountLoader<'info, MintInfo>, + #[account(mut)] pub payer: Signer<'info>, @@ -56,8 +59,6 @@ pub struct TokenAddBank<'info> { pub rent: Sysvar<'info, Rent>, } -// 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( @@ -65,11 +66,10 @@ pub fn token_add_bank( token_index: TokenIndex, bank_num: u32, ) -> Result<()> { - // TODO: Error if mint is already configured (technically, init of vault will fail) - let existing_bank = ctx.accounts.existing_bank.load()?; let mut bank = ctx.accounts.bank.load_init()?; - *bank = Bank::from_existing_bank(&existing_bank, ctx.accounts.vault.key(), bank_num); + let bump = *ctx.bumps.get("bank").ok_or(MangoError::SomeError)?; + *bank = Bank::from_existing_bank(&existing_bank, ctx.accounts.vault.key(), bank_num, bump); let mut mint_info = ctx.accounts.mint_info.load_mut()?; let free_slot = mint_info diff --git a/programs/mango-v4/src/instructions/token_deposit.rs b/programs/mango-v4/src/instructions/token_deposit.rs index 22afcfc88..28a8598fd 100644 --- a/programs/mango-v4/src/instructions/token_deposit.rs +++ b/programs/mango-v4/src/instructions/token_deposit.rs @@ -48,9 +48,6 @@ impl<'info> TokenDeposit<'info> { } } -// TODO: It may make sense to have the token_index passed in from the outside. -// That would save a lot of computation that needs to go into finding the -// right index for the mint. pub fn token_deposit(ctx: Context, amount: u64) -> Result<()> { require_msg!(amount > 0, "deposit amount must be positive"); diff --git a/programs/mango-v4/src/instructions/token_edit.rs b/programs/mango-v4/src/instructions/token_edit.rs index ab4100f00..6e907cfc1 100644 --- a/programs/mango-v4/src/instructions/token_edit.rs +++ b/programs/mango-v4/src/instructions/token_edit.rs @@ -7,6 +7,10 @@ use crate::accounts_zerocopy::LoadMutZeroCopyRef; use crate::state::*; +/// Changes a token's parameters. +/// +/// In addition to these accounts, all banks must be passed as remaining_accounts +/// in MintInfo order. #[derive(Accounts)] #[instruction(bank_num: u64)] pub struct TokenEdit<'info> { diff --git a/programs/mango-v4/src/instructions/token_register.rs b/programs/mango-v4/src/instructions/token_register.rs index 453d37f86..ad71ac055 100644 --- a/programs/mango-v4/src/instructions/token_register.rs +++ b/programs/mango-v4/src/instructions/token_register.rs @@ -73,8 +73,6 @@ pub struct InterestRateParams { pub adjustment_factor: f32, } -// 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)] pub fn token_register( ctx: Context, diff --git a/programs/mango-v4/src/instructions/token_update_index_and_rate.rs b/programs/mango-v4/src/instructions/token_update_index_and_rate.rs index ea703f251..8867c237a 100644 --- a/programs/mango-v4/src/instructions/token_update_index_and_rate.rs +++ b/programs/mango-v4/src/instructions/token_update_index_and_rate.rs @@ -17,6 +17,13 @@ pub mod compute_budget { declare_id!("ComputeBudget111111111111111111111111111111"); } +/// Updates token interest and interest rates. +/// +/// In addition to these accounts, all banks must be passed as remaining_accounts +/// in MintInfo order. +/// +/// This instruction may only be used alongside other instructions of the same kind +/// or ComputeBudget instructions. #[derive(Accounts)] pub struct TokenUpdateIndexAndRate<'info> { pub group: AccountLoader<'info, Group>, // Required for group metadata parsing diff --git a/programs/mango-v4/src/lib.rs b/programs/mango-v4/src/lib.rs index be25edab5..2f7082231 100644 --- a/programs/mango-v4/src/lib.rs +++ b/programs/mango-v4/src/lib.rs @@ -41,10 +41,18 @@ pub mod mango_v4 { pub fn group_edit( ctx: Context, - new_admin: Pubkey, - new_fast_listing_admin: Pubkey, + admin_opt: Option, + fast_listing_admin_opt: Option, + testing_opt: Option, + version_opt: Option, ) -> Result<()> { - instructions::group_edit(ctx, new_admin, new_fast_listing_admin) + instructions::group_edit( + ctx, + admin_opt, + fast_listing_admin_opt, + testing_opt, + version_opt, + ) } pub fn group_close(ctx: Context) -> Result<()> { diff --git a/programs/mango-v4/src/state/bank.rs b/programs/mango-v4/src/state/bank.rs index cb8b9ddb1..9ca3f5ce7 100644 --- a/programs/mango-v4/src/state/bank.rs +++ b/programs/mango-v4/src/state/bank.rs @@ -109,20 +109,36 @@ const_assert_eq!( const_assert_eq!(size_of::() % 8, 0); impl Bank { - pub fn from_existing_bank(existing_bank: &Bank, vault: Pubkey, bank_num: u32) -> Self { + pub fn from_existing_bank( + existing_bank: &Bank, + vault: Pubkey, + bank_num: u32, + bump: u8, + ) -> Self { Self { + // values that must be reset/changed + vault, + indexed_deposits: I80F48::ZERO, + indexed_borrows: I80F48::ZERO, + collected_fees_native: I80F48::ZERO, + dust: I80F48::ZERO, + flash_loan_approved_amount: 0, + flash_loan_token_account_initial: u64::MAX, + bump, + bank_num, + + // values that can be copied + // these are listed explicitly, so someone must make the decision when a + // new field is added! name: existing_bank.name, group: existing_bank.group, mint: existing_bank.mint, - vault, oracle: existing_bank.oracle, oracle_config: existing_bank.oracle_config, deposit_index: existing_bank.deposit_index, borrow_index: existing_bank.borrow_index, cached_indexed_total_deposits: existing_bank.cached_indexed_total_deposits, cached_indexed_total_borrows: existing_bank.cached_indexed_total_borrows, - indexed_deposits: I80F48::ZERO, - indexed_borrows: I80F48::ZERO, index_last_updated: existing_bank.index_last_updated, bank_rate_last_updated: existing_bank.bank_rate_last_updated, avg_utilization: existing_bank.avg_utilization, @@ -132,7 +148,6 @@ impl Bank { util1: existing_bank.util1, rate1: existing_bank.rate1, max_rate: existing_bank.max_rate, - collected_fees_native: existing_bank.collected_fees_native, loan_origination_fee_rate: existing_bank.loan_origination_fee_rate, loan_fee_rate: existing_bank.loan_fee_rate, maint_asset_weight: existing_bank.maint_asset_weight, @@ -140,14 +155,9 @@ impl Bank { maint_liab_weight: existing_bank.maint_liab_weight, init_liab_weight: existing_bank.init_liab_weight, liquidation_fee: existing_bank.liquidation_fee, - dust: I80F48::ZERO, - flash_loan_approved_amount: 0, - flash_loan_token_account_initial: u64::MAX, token_index: existing_bank.token_index, - bump: existing_bank.bump, mint_decimals: existing_bank.mint_decimals, reserved: [0; 2560], - bank_num, } } diff --git a/programs/mango-v4/src/state/mango_account.rs b/programs/mango-v4/src/state/mango_account.rs index 5e0096c2a..859cdd641 100644 --- a/programs/mango-v4/src/state/mango_account.rs +++ b/programs/mango-v4/src/state/mango_account.rs @@ -956,14 +956,10 @@ impl< } } - // update header - let header_mut = self.header_mut(); - header_mut.token_count = new_token_count; - header_mut.serum3_count = new_serum3_count; - header_mut.perp_count = new_perp_count; - header_mut.perp_oo_count = new_perp_oo_count; + // update the already-parsed header + *self.header_mut() = new_header; - // write new lengths (uses header) + // write new lengths to the dynamic data (uses header) self.write_token_length(); self.write_serum3_length(); self.write_perp_length(); diff --git a/ts/client/src/client.ts b/ts/client/src/client.ts index d71a673ec..ecd4f46ea 100644 --- a/ts/client/src/client.ts +++ b/ts/client/src/client.ts @@ -94,11 +94,18 @@ export class MangoClient { public async groupEdit( group: Group, - newAdmin: PublicKey, - newFastListingAdmin: PublicKey, + admin: PublicKey | undefined, + fastListingAdmin: PublicKey | undefined, + testing: number | undefined, + version: number | undefined, ): Promise { return await this.program.methods - .groupEdit(newAdmin, newFastListingAdmin) + .groupEdit( + admin ?? null, + fastListingAdmin ?? null, + testing ?? null, + version ?? null, + ) .accounts({ group: group.publicKey, admin: (this.program.provider as AnchorProvider).wallet.publicKey, diff --git a/ts/client/src/mango_v4.ts b/ts/client/src/mango_v4.ts index d048e276a..c7cf653f5 100644 --- a/ts/client/src/mango_v4.ts +++ b/ts/client/src/mango_v4.ts @@ -110,12 +110,28 @@ export type MangoV4 = { ], "args": [ { - "name": "newAdmin", - "type": "publicKey" + "name": "adminOpt", + "type": { + "option": "publicKey" + } }, { - "name": "newFastListingAdmin", - "type": "publicKey" + "name": "fastListingAdminOpt", + "type": { + "option": "publicKey" + } + }, + { + "name": "testingOpt", + "type": { + "option": "u8" + } + }, + { + "name": "versionOpt", + "type": { + "option": "u8" + } } ] }, @@ -646,27 +662,7 @@ export type MangoV4 = { { "name": "mintInfo", "isMut": true, - "isSigner": false, - "pda": { - "seeds": [ - { - "kind": "const", - "type": "string", - "value": "MintInfo" - }, - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, - { - "kind": "account", - "type": "publicKey", - "account": "Mint", - "path": "mint" - } - ] - } + "isSigner": false }, { "name": "payer", @@ -5150,12 +5146,28 @@ export const IDL: MangoV4 = { ], "args": [ { - "name": "newAdmin", - "type": "publicKey" + "name": "adminOpt", + "type": { + "option": "publicKey" + } }, { - "name": "newFastListingAdmin", - "type": "publicKey" + "name": "fastListingAdminOpt", + "type": { + "option": "publicKey" + } + }, + { + "name": "testingOpt", + "type": { + "option": "u8" + } + }, + { + "name": "versionOpt", + "type": { + "option": "u8" + } } ] }, @@ -5686,27 +5698,7 @@ export const IDL: MangoV4 = { { "name": "mintInfo", "isMut": true, - "isSigner": false, - "pda": { - "seeds": [ - { - "kind": "const", - "type": "string", - "value": "MintInfo" - }, - { - "kind": "account", - "type": "publicKey", - "path": "group" - }, - { - "kind": "account", - "type": "publicKey", - "account": "Mint", - "path": "mint" - } - ] - } + "isSigner": false }, { "name": "payer", diff --git a/ts/client/src/scripts/example1-admin.ts b/ts/client/src/scripts/example1-admin.ts index dea291ad7..99a629833 100644 --- a/ts/client/src/scripts/example1-admin.ts +++ b/ts/client/src/scripts/example1-admin.ts @@ -204,6 +204,8 @@ async function main() { group, group.admin, new PublicKey('Efhak3qj3MiyzgJr3cUUqXXz5wr3oYHt9sPzuqJf9eBN'), + undefined, + undefined, ); console.log(`sig https://explorer.solana.com/tx/${sig}?cluster=devnet`); console.log(`Registering MNGO...`); diff --git a/ts/client/src/scripts/mb-example1-admin.ts b/ts/client/src/scripts/mb-example1-admin.ts index 7f12a5b45..c22a6c69c 100644 --- a/ts/client/src/scripts/mb-example1-admin.ts +++ b/ts/client/src/scripts/mb-example1-admin.ts @@ -209,7 +209,7 @@ async function main() { ); console.log(`Registering MNGO...`); - await client.groupEdit(group, group.admin, group.admin); + await client.groupEdit(group, group.admin, group.admin, undefined, undefined); const mngoMainnetMint = new PublicKey(MAINNET_MINTS.get('MNGO')!); const mngoMainnetOracle = new PublicKey(MAINNET_ORACLES.get('MNGO')!); await client.tokenRegisterTrustless(