diff --git a/.github/workflows/ci-code-review-ts.yml b/.github/workflows/ci-code-review-ts.yml index c13b09566..9e5cb78ff 100644 --- a/.github/workflows/ci-code-review-ts.yml +++ b/.github/workflows/ci-code-review-ts.yml @@ -11,7 +11,6 @@ jobs: format: name: Format runs-on: ubuntu-latest - if: (github.actor != 'dependabot[bot]') steps: - name: Checkout code uses: actions/checkout@v3 @@ -31,7 +30,6 @@ jobs: lint: name: Lint runs-on: ubuntu-latest - if: (github.actor != 'dependabot[bot]') steps: - name: Checkout code uses: actions/checkout@v3 @@ -51,7 +49,6 @@ jobs: unit-test: name: Unit Test runs-on: ubuntu-latest - if: (github.actor != 'dependabot[bot]') steps: - name: Checkout code uses: actions/checkout@v3 @@ -71,7 +68,6 @@ jobs: semgrep: name: Security Scan runs-on: ubuntu-latest - if: (github.actor != 'dependabot[bot]') container: image: returntocorp/semgrep @@ -80,6 +76,12 @@ jobs: uses: actions/checkout@v3 - name: Run semgrep - run: semgrep ci + run: semgrep ci --sarif --output=semgrep-results.sarif env: SEMGREP_RULES: p/typescript + + - name: Upload output + uses: github/codeql-action/upload-sarif@v2 + if: always() + with: + sarif_file: semgrep-results.sarif diff --git a/.github/workflows/ci-dependency-scan-cargo.yml b/.github/workflows/ci-dependency-scan-cargo.yml index ef63a7e22..bd7348e65 100644 --- a/.github/workflows/ci-dependency-scan-cargo.yml +++ b/.github/workflows/ci-dependency-scan-cargo.yml @@ -25,12 +25,11 @@ jobs: trivy: name: Dependency Scan runs-on: ubuntu-latest - if: (github.actor != 'dependabot[bot]') steps: - name: Checkout code uses: actions/checkout@v3 - # Report all vulnerabilities in CI output + # Report all vulnerabilities in security tab - name: Report on all vulnerabilities uses: aquasecurity/trivy-action@master with: @@ -38,7 +37,8 @@ jobs: scan-ref: 'Cargo.lock' ignore-unfixed: true hide-progress: true - format: 'table' + format: 'sarif' + output: 'trivy-results.sarif' # Fail the job on critical vulnerabiliies with fix available - name: Fail on critical vulnerabilities @@ -51,3 +51,9 @@ jobs: format: 'table' severity: 'CRITICAL' exit-code: '1' + + - name: Upload output + uses: github/codeql-action/upload-sarif@v2 + if: always() + with: + sarif_file: 'trivy-results.sarif' \ No newline at end of file diff --git a/.github/workflows/ci-dependency-scan-yarn.yml b/.github/workflows/ci-dependency-scan-yarn.yml index ce11d23a0..00af7615c 100644 --- a/.github/workflows/ci-dependency-scan-yarn.yml +++ b/.github/workflows/ci-dependency-scan-yarn.yml @@ -11,12 +11,11 @@ jobs: trivy: name: Dependency Scan runs-on: ubuntu-latest - if: (github.actor != 'dependabot[bot]') steps: - name: Checkout code uses: actions/checkout@v3 - # Report all vulnerabilities in CI output + # Report all vulnerabilities in security tab - name: Report on all vulnerabilities uses: aquasecurity/trivy-action@master with: @@ -24,7 +23,8 @@ jobs: scan-ref: 'yarn.lock' ignore-unfixed: true hide-progress: true - format: 'table' + format: 'sarif' + output: 'trivy-results.sarif' # Fail the job on critical vulnerabiliies with fix available - name: Fail on critical vulnerabilities @@ -37,3 +37,9 @@ jobs: format: 'table' severity: 'CRITICAL' exit-code: '1' + + - name: Upload output + uses: github/codeql-action/upload-sarif@v2 + if: always() + with: + sarif_file: 'trivy-results.sarif' \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 784a153a4..0364c5d48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,42 +1,55 @@ # Mango v4 Program Change Log -Update this for each mainnet deployment. +Update this for each program release and mainnet deployment. ## not on mainnet ## mainnet -Jan 5, 2023 Central European Standard Time +### v0.2.0, 2023-1-13 + +Deployment: Jan 13, 2023 at 11:31:05 Central European Standard Time, https://explorer.solana.com/tx/4yGRUk6QwntvC4umECDPDZJNcbevSJ1fdZi75Mz9rGa9SHKzUtjMF3V5FCTkzBZqAETQTccqv63BYw6yX8JNxiur + +- Add an optional security authority with the ability to halt a group or + temporarily freeze user accounts. +- Extend perp pnl settle limits to apply to realized pnl +- Rename perp_liq_bankruptcy to perp_liq_quote_and_bankruptcy and extend it to + cover taking over the liqee's negative pnl while the settle limits and perp + settle health allow it. +- Perp bankruptcy is now allowed when settling is impossible, even when there are + spot assets remaining. + +### Jan 5, 2023 Central European Standard Time - Change max staleness slots from -1 to 600 for trustless token registering -Jan 4, 2023 Central European Standard Time +### Jan 4, 2023 Central European Standard Time - Reduce only mode for tokens, and perp markets - Perp settlement applies no loan origination fee -Dec 16, 2022 at 16:40 Central European Standard Time +### Dec 16, 2022 at 16:40 Central European Standard Time -Oct 8, 2022 at 14:38:31 Central European Summer Time +### Oct 8, 2022 at 14:38:31 Central European Summer Time https://explorer.solana.com/tx/3m8EDohkgwJZyiwpGXztBWARWQVxyhnSNDVuH467D7FPS2wxJerr79HhdhDEed5hpConHgGsKHvxtW1HJP6GixX9 -Oct 8, 2022 at 14:38:31 Central European Summer Time +### Oct 8, 2022 at 14:38:31 Central European Summer Time https://explorer.solana.com/tx/3m8EDohkgwJZyiwpGXztBWARWQVxyhnSNDVuH467D7FPS2wxJerr79HhdhDEed5hpConHgGsKHvxtW1HJP6GixX9 - New ix `TokenDepositIntoExisting` -Sep 1, 2022 at 10:24:35 Central European Summer Time +### Sep 1, 2022 at 10:24:35 Central European Summer Time https://explorer.solana.com/tx/3NnX13A3QwsREKKKo3iYR4jqgoongpCjdhhXuJ3y5iP6FwfPcNieVop623tpgPbyreC7m7KtphwdWdoHYE5YC394 - Add HealthRegionBegin, -End instructions - Add explicit "oracle" account argument for TokenDeposit and TokenWithdraw instructions -Aug 20, 2022 at 19:58:29 Central European Summer Time +### Aug 20, 2022 at 19:58:29 Central European Summer Time https://explorer.solana.com/tx/3R4frko1AekQKJmmQ5T6k3mdXF9uZVHTR7oocdspTPsc82xX7qrbgnG61r28UdhCxsjMxtQHgBqMc37FSvoHQfCN - loan fee logging for off-chain services -Aug 18, 2022 at 17:17:40 Central European Summer Time +### Aug 18, 2022 at 17:17:40 Central European Summer Time https://explorer.solana.com/tx/4Xnyswcwx98y6khw8ptNVmdhQZwJjuNy2BvmQg2pJayoThFiw8kmS2ecRAg5cg2DncvW3NQgn2vtP8mCUtv6Q1yB - liq_token_bankruptcy: removed liab_token_index argument @@ -82,13 +95,13 @@ https://explorer.solana.com/tx/4Xnyswcwx98y6khw8ptNVmdhQZwJjuNy2BvmQg2pJayoThFiw marginTrade takes inputMintPk and outputMintPk instead of inputToken and outputToken marginTrade takes flashLoanType as an argument -Aug 8, 2022 at 18:56:04 Central European Summer Time +### Aug 8, 2022 at 18:56:04 Central European Summer Time https://explorer.solana.com/tx/yjZggRTrcDNquMkftNvBKLv77Dk4xp5yQPYXgN3qvBHTBWWJVhLPGHxqpGwosmEq3j8byHZMa13oxLLerBWUdgW - improved logging for off chain services - `AccountCreate` ix takes explicit input for sizes of various features -Aug 4, 2022 at 09:30:00 Central European Summer Time +### Aug 4, 2022 at 09:30:00 Central European Summer Time ts/client changes @@ -114,7 +127,7 @@ New features - `TokenRegistration` and `TokenRegisterTrustless` ixs dont take a bank_num anymore, hardcoded to 0. - Enforced a minimum maximum rate of 50% so that rates don't fall so low that they cannot recover. -Jul 14, 2022 at 09:33:52 Central European Summer Time +### Jul 14, 2022 at 09:33:52 Central European Summer Time https://explorer.solana.com/tx/vZ5hP1vGp37fgzBfG9nb4nfA5ZdmYgk8meq53YPR4ReFxrcTwBUxTYBQUgnfAnq9u5fH36S3QTfb9mVkBXt5A6C - Account data was rearranged to put fields that are often used with gPA first diff --git a/Cargo.lock b/Cargo.lock index 377c7f76a..ffc313991 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1094,7 +1094,7 @@ dependencies = [ [[package]] name = "cli" -version = "0.1.0" +version = "0.3.0" dependencies = [ "anchor-client", "anchor-lang", @@ -1118,7 +1118,7 @@ dependencies = [ [[package]] name = "client" -version = "0.1.0" +version = "0.3.0" dependencies = [ "anchor-client", "anchor-lang", @@ -2846,7 +2846,7 @@ dependencies = [ [[package]] name = "keeper" -version = "0.1.0" +version = "0.3.0" dependencies = [ "anchor-client", "anchor-lang", @@ -3121,7 +3121,7 @@ dependencies = [ [[package]] name = "mango-v4" -version = "0.1.0" +version = "0.3.0" dependencies = [ "anchor-lang", "anchor-spl", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 7fb316b69..0be673b52 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cli" -version = "0.1.0" +version = "0.3.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/client/Cargo.toml b/client/Cargo.toml index ffda6c0d2..b0b27e176 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "client" -version = "0.1.0" +version = "0.3.0" edition = "2021" [lib] diff --git a/keeper/Cargo.toml b/keeper/Cargo.toml index 8f78b2a3c..9c31f0fa5 100644 --- a/keeper/Cargo.toml +++ b/keeper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "keeper" -version = "0.1.0" +version = "0.3.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/programs/mango-v4/Cargo.toml b/programs/mango-v4/Cargo.toml index afe893f93..ef3e57331 100644 --- a/programs/mango-v4/Cargo.toml +++ b/programs/mango-v4/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mango-v4" -version = "0.1.0" +version = "0.3.0" description = "Created with Anchor" edition = "2021" diff --git a/programs/mango-v4/src/health/cache.rs b/programs/mango-v4/src/health/cache.rs index 17e7da705..df0b6abea 100644 --- a/programs/mango-v4/src/health/cache.rs +++ b/programs/mango-v4/src/health/cache.rs @@ -537,21 +537,6 @@ impl HealthCache { self.has_spot_borrows() || perp_borrows } - pub fn has_liquidatable_spot_or_perp_base(&self) -> bool { - let spot_liquidatable = self.has_spot_assets(); - let serum3_cancelable = self.has_serum3_open_orders_funds(); - let perp_liquidatable = self.perp_infos.iter().any(|p| { - // can use perp_liq_base_position - p.base_lots != 0 - // can use perp_liq_force_cancel_orders - || p.has_open_orders - // A remaining quote position can be reduced with perp_settle_pnl and that can improve health. - // However, since it's not guaranteed that there is a counterparty, a positive perp quote position - // does not prevent bankruptcy. - }); - spot_liquidatable || serum3_cancelable || perp_liquidatable - } - pub(crate) fn compute_serum3_reservations( &self, health_type: HealthType, diff --git a/programs/mango-v4/src/i80f48.rs b/programs/mango-v4/src/i80f48.rs index f7a84fd43..94c34d7a1 100644 --- a/programs/mango-v4/src/i80f48.rs +++ b/programs/mango-v4/src/i80f48.rs @@ -1,11 +1,11 @@ use fixed::types::I80F48; -pub trait ClampedToNum { +pub trait ClampToInt { fn clamp_to_i64(&self) -> i64; fn clamp_to_u64(&self) -> u64; } -impl ClampedToNum for I80F48 { +impl ClampToInt for I80F48 { fn clamp_to_i64(&self) -> i64 { if *self <= i64::MIN { i64::MIN @@ -27,7 +27,7 @@ impl ClampedToNum for I80F48 { } } -impl ClampedToNum for f64 { +impl ClampToInt for f64 { fn clamp_to_i64(&self) -> i64 { if *self <= i64::MIN as f64 { i64::MIN @@ -49,7 +49,7 @@ impl ClampedToNum for f64 { } } -impl ClampedToNum for u64 { +impl ClampToInt for u64 { fn clamp_to_i64(&self) -> i64 { if *self >= i64::MAX as u64 { i64::MAX diff --git a/programs/mango-v4/src/instructions/perp_liq_base_position.rs b/programs/mango-v4/src/instructions/perp_liq_base_position.rs index ccbba07db..7ccdc3f44 100644 --- a/programs/mango-v4/src/instructions/perp_liq_base_position.rs +++ b/programs/mango-v4/src/instructions/perp_liq_base_position.rs @@ -71,24 +71,8 @@ pub fn perp_liq_base_position( let liqee_init_health = liqee_health_cache.health(HealthType::Init); liqee_health_cache.require_after_phase1_liquidation()?; - // Once maint_health falls below 0, we want to start liquidating, - // we want to allow liquidation to continue until init_health is positive, - // to prevent constant oscillation between the two states - if liqee.being_liquidated() { - if liqee - .fixed - .maybe_recover_from_being_liquidated(liqee_init_health) - { - msg!("Liqee init_health above zero"); - return Ok(()); - } - } else { - let maint_health = liqee_health_cache.health(HealthType::Maint); - require!( - maint_health < I80F48::ZERO, - MangoError::HealthMustBeNegative - ); - liqee.fixed.set_being_liquidated(true); + if !liqee.check_liquidatable(&liqee_health_cache)? { + return Ok(()); } let mut perp_market = ctx.accounts.perp_market.load_mut()?; diff --git a/programs/mango-v4/src/instructions/perp_liq_force_cancel_orders.rs b/programs/mango-v4/src/instructions/perp_liq_force_cancel_orders.rs index 6d9785304..a4611f291 100644 --- a/programs/mango-v4/src/instructions/perp_liq_force_cancel_orders.rs +++ b/programs/mango-v4/src/instructions/perp_liq_force_cancel_orders.rs @@ -1,5 +1,4 @@ use anchor_lang::prelude::*; -use fixed::types::I80F48; use crate::error::*; use crate::health::*; @@ -47,22 +46,20 @@ pub fn perp_liq_force_cancel_orders( let health_cache = new_health_cache(&account.borrow(), &retriever).context("create health cache")?; - if account.being_liquidated() { - let init_health = health_cache.health(HealthType::Init); - if account - .fixed - .maybe_recover_from_being_liquidated(init_health) - { - msg!("Liqee init_health above zero"); - return Ok(()); + { + let result = account.check_liquidatable(&health_cache); + if account.fixed.is_operational() { + if !result? { + return Ok(()); + } + } else { + // Frozen accounts can always have their orders cancelled + if let Err(Error::AnchorError(ref inner)) = result { + if inner.error_code_number != MangoError::HealthMustBeNegative as u32 { + result?; + } + } } - } else { - let maint_health = health_cache.health(HealthType::Maint); - require!( - maint_health < I80F48::ZERO, - MangoError::HealthMustBeNegative - ); - account.fixed.set_being_liquidated(true); } health_cache diff --git a/programs/mango-v4/src/instructions/perp_liq_quote_and_bankruptcy.rs b/programs/mango-v4/src/instructions/perp_liq_quote_and_bankruptcy.rs index 0acbca735..e2c273677 100644 --- a/programs/mango-v4/src/instructions/perp_liq_quote_and_bankruptcy.rs +++ b/programs/mango-v4/src/instructions/perp_liq_quote_and_bankruptcy.rs @@ -118,24 +118,8 @@ pub fn perp_liq_quote_and_bankruptcy( let liqee_settle_health = liqee_health_cache.perp_settle_health(); liqee_health_cache.require_after_phase2_liquidation()?; - // Once maint_health falls below 0, we want to start liquidating, - // we want to allow liquidation to continue until init_health is positive, - // to prevent constant oscillation between the two states - if liqee.being_liquidated() { - if liqee - .fixed - .maybe_recover_from_being_liquidated(liqee_init_health) - { - msg!("Liqee init_health above zero"); - return Ok(()); - } - } else { - let maint_health = liqee_health_cache.health(HealthType::Maint); - require!( - maint_health < I80F48::ZERO, - MangoError::HealthMustBeNegative - ); - liqee.fixed.set_being_liquidated(true); + if !liqee.check_liquidatable(&liqee_health_cache)? { + return Ok(()); } // check positions exist/create them, done early for nicer error messages diff --git a/programs/mango-v4/src/instructions/serum3_liq_force_cancel_orders.rs b/programs/mango-v4/src/instructions/serum3_liq_force_cancel_orders.rs index 744ad64c6..6744b74d2 100644 --- a/programs/mango-v4/src/instructions/serum3_liq_force_cancel_orders.rs +++ b/programs/mango-v4/src/instructions/serum3_liq_force_cancel_orders.rs @@ -1,6 +1,5 @@ use anchor_lang::prelude::*; use anchor_spl::token::{Token, TokenAccount}; -use fixed::types::I80F48; use crate::error::*; use crate::health::*; @@ -126,22 +125,21 @@ pub fn serum3_liq_force_cancel_orders( let health_cache = new_health_cache(&account.borrow(), &retriever).context("create health cache")?; - if account.being_liquidated() { - let init_health = health_cache.health(HealthType::Init); - if account - .fixed - .maybe_recover_from_being_liquidated(init_health) - { - msg!("Liqee init_health above zero"); - return Ok(()); + { + let result = account.check_liquidatable(&health_cache); + if account.fixed.is_operational() { + if !result? { + return Ok(()); + } + } else { + // Frozen accounts can always have their orders cancelled + if let Err(Error::AnchorError(ref inner)) = result { + if inner.error_code_number != MangoError::HealthMustBeNegative as u32 { + // propagate all unexpected errors + result?; + } + } } - } else { - let maint_health = health_cache.health(HealthType::Maint); - require!( - maint_health < I80F48::ZERO, - MangoError::HealthMustBeNegative - ); - account.fixed.set_being_liquidated(true); } health_cache diff --git a/programs/mango-v4/src/instructions/token_liq_with_token.rs b/programs/mango-v4/src/instructions/token_liq_with_token.rs index b63278f1e..fc8713bbf 100644 --- a/programs/mango-v4/src/instructions/token_liq_with_token.rs +++ b/programs/mango-v4/src/instructions/token_liq_with_token.rs @@ -69,21 +69,8 @@ pub fn token_liq_with_token( let init_health = liqee_health_cache.health(HealthType::Init); liqee_health_cache.require_after_phase1_liquidation()?; - // Once maint_health falls below 0, we want to start liquidating, - // we want to allow liquidation to continue until init_health is positive, - // to prevent constant oscillation between the two states - if liqee.being_liquidated() { - if liqee.fixed.maybe_recover_from_being_liquidated(init_health) { - msg!("Liqee init_health above zero"); - return Ok(()); - } - } else { - let maint_health = liqee_health_cache.health(HealthType::Maint); - require!( - maint_health < I80F48::ZERO, - MangoError::HealthMustBeNegative - ); - liqee.fixed.set_being_liquidated(true); + if !liqee.check_liquidatable(&liqee_health_cache)? { + return Ok(()); } // diff --git a/programs/mango-v4/src/state/mango_account.rs b/programs/mango-v4/src/state/mango_account.rs index 343f08a07..fa9c6300c 100644 --- a/programs/mango-v4/src/state/mango_account.rs +++ b/programs/mango-v4/src/state/mango_account.rs @@ -86,7 +86,7 @@ pub struct MangoAccount { /// Init health as calculated during HealthReginBegin, rounded up. pub health_region_begin_init_health: i64, - pub frozen_until: i64, + pub frozen_until: u64, pub reserved: [u8; 232], @@ -968,6 +968,30 @@ impl< Ok(()) } + pub fn check_liquidatable(&mut self, health_cache: &HealthCache) -> Result { + // Once maint_health falls below 0, we want to start liquidating, + // we want to allow liquidation to continue until init_health is positive, + // to prevent constant oscillation between the two states + if self.being_liquidated() { + let init_health = health_cache.health(HealthType::Init); + if self + .fixed_mut() + .maybe_recover_from_being_liquidated(init_health) + { + msg!("Liqee init_health above zero"); + return Ok(false); + } + } else { + let maint_health = health_cache.health(HealthType::Maint); + require!( + maint_health < I80F48::ZERO, + MangoError::HealthMustBeNegative + ); + self.fixed_mut().set_being_liquidated(true); + } + Ok(true) + } + // writes length of tokens vec at appropriate offset so that borsh can infer the vector length // length used is that present in the header fn write_token_length(&mut self) { diff --git a/programs/mango-v4/src/state/mango_account_components.rs b/programs/mango-v4/src/state/mango_account_components.rs index b80261d7c..cb4813c8e 100644 --- a/programs/mango-v4/src/state/mango_account_components.rs +++ b/programs/mango-v4/src/state/mango_account_components.rs @@ -6,7 +6,7 @@ use static_assertions::const_assert_eq; use std::cmp::Ordering; use std::mem::size_of; -use crate::i80f48::ClampedToNum; +use crate::i80f48::ClampToInt; use crate::state::*; pub const FREE_ORDER_SLOT: PerpMarketIndex = PerpMarketIndex::MAX; diff --git a/ts/client/src/client.ts b/ts/client/src/client.ts index 1022375ab..097765062 100644 --- a/ts/client/src/client.ts +++ b/ts/client/src/client.ts @@ -58,7 +58,7 @@ import { } from './utils'; import { sendTransaction } from './utils/rpc'; -enum AccountRetriever { +export enum AccountRetriever { Scanning, Fixed, } @@ -2657,9 +2657,7 @@ export class MangoClient { ); } - /// private - - private buildHealthRemainingAccounts( + public buildHealthRemainingAccounts( retriever: AccountRetriever, group: Group, mangoAccounts: MangoAccount[], @@ -2699,12 +2697,12 @@ export class MangoClient { const tokenPositionIndices = mangoAccount.tokens.map((t) => t.tokenIndex); for (const bank of banks) { const tokenPositionExists = - tokenPositionIndices.indexOf(bank.tokenIndex) > 0; + tokenPositionIndices.indexOf(bank.tokenIndex) > -1; if (!tokenPositionExists) { const inactiveTokenPosition = tokenPositionIndices.findIndex( (index) => index === TokenPosition.TokenIndexUnset, ); - if (inactiveTokenPosition) { + if (inactiveTokenPosition != -1) { tokenPositionIndices[inactiveTokenPosition] = bank.tokenIndex; } } @@ -2724,12 +2722,12 @@ export class MangoClient { const perpPositionIndices = mangoAccount.perps.map((p) => p.marketIndex); for (const perpMarket of perpMarkets) { const perpPositionExists = - perpPositionIndices.indexOf(perpMarket.perpMarketIndex) > 0; + perpPositionIndices.indexOf(perpMarket.perpMarketIndex) > -1; if (!perpPositionExists) { - const inactivePerpPosition = perpPositionIndices.find( + const inactivePerpPosition = perpPositionIndices.findIndex( (perpIdx) => perpIdx === PerpPosition.PerpMarketIndexUnset, ); - if (inactivePerpPosition) { + if (inactivePerpPosition != -1) { perpPositionIndices[inactivePerpPosition] = perpMarket.perpMarketIndex; } @@ -2753,15 +2751,16 @@ export class MangoClient { const ooPositionExists = serumPositionIndices.findIndex( (i) => i.marketIndex === serum3Market.marketIndex, - ) > 0; + ) > -1; if (!ooPositionExists) { - const inactiveSerumPosition = serumPositionIndices.find( + const inactiveSerumPosition = serumPositionIndices.findIndex( (serumPos) => serumPos.marketIndex === Serum3Orders.Serum3MarketIndexUnset, ); - if (inactiveSerumPosition) { - inactiveSerumPosition.marketIndex = serum3Market.marketIndex; - inactiveSerumPosition.openOrders = openOrderPk; + if (inactiveSerumPosition != -1) { + serumPositionIndices[inactiveSerumPosition].marketIndex = + serum3Market.marketIndex; + serumPositionIndices[inactiveSerumPosition].openOrders = openOrderPk; } } } diff --git a/ts/client/src/mango_v4.ts b/ts/client/src/mango_v4.ts index e8afc8ec9..ad53665bd 100644 --- a/ts/client/src/mango_v4.ts +++ b/ts/client/src/mango_v4.ts @@ -1,5 +1,5 @@ export type MangoV4 = { - "version": "0.1.0", + "version": "0.2.0", "name": "mango_v4", "instructions": [ { @@ -4030,7 +4030,7 @@ export type MangoV4 = { }, { "name": "frozenUntil", - "type": "i64" + "type": "u64" }, { "name": "reserved", @@ -7717,7 +7717,7 @@ export type MangoV4 = { }; export const IDL: MangoV4 = { - "version": "0.1.0", + "version": "0.2.0", "name": "mango_v4", "instructions": [ { @@ -11748,7 +11748,7 @@ export const IDL: MangoV4 = { }, { "name": "frozenUntil", - "type": "i64" + "type": "u64" }, { "name": "reserved", diff --git a/ts/client/src/scripts/mb-admin.ts b/ts/client/src/scripts/mb-admin.ts index ef718064c..f8b5467ca 100644 --- a/ts/client/src/scripts/mb-admin.ts +++ b/ts/client/src/scripts/mb-admin.ts @@ -509,6 +509,45 @@ async function makePerpMarketReduceOnly() { ); } +async function makePerpMarketUntrusted() { + const result = await buildAdminClient(); + const client = result[0]; + const admin = result[1]; + const creator = result[2]; + + const group = await client.getGroupForCreator(creator.publicKey, GROUP_NUM); + const perpMarket = group.getPerpMarketByName('BTC-PERP'); + await client.perpEditMarket( + group, + perpMarket.perpMarketIndex, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + false, + null, + null, + null, + null, + null, + null, + null, + null, + null, + ); +} + async function createAndPopulateAlt() { const result = await buildAdminClient(); const client = result[0]; @@ -669,6 +708,7 @@ async function main() { try { // await registerPerpMarkets(); // await makePerpMarketReduceOnly(); + // await makePerpMarketUntrusted(); } catch (error) { console.log(error); }