diff --git a/programs/manifest/src/program/processor/batch_update.rs b/programs/manifest/src/program/processor/batch_update.rs index 023fe208b..4d8de8ccd 100644 --- a/programs/manifest/src/program/processor/batch_update.rs +++ b/programs/manifest/src/program/processor/batch_update.rs @@ -173,10 +173,11 @@ pub(crate) fn process_batch_update( &global_trade_accounts_opts, )?; } - Some(hinted_index) => { + Some(hinted_cancel_index) => { // TODO: Verify that it is an order at the index, not a // ClaimedSeat that a malicious user pretended was a seat. - let order: &RestingOrder = dynamic_account.get_order_by_index(hinted_index); + let order: &RestingOrder = + dynamic_account.get_order_by_index(hinted_cancel_index); // Simple sanity check on the hint given. Make sure that it // aligns with block boundaries. We do a check that it is an // order owned by the payer inside the handler. @@ -184,11 +185,11 @@ pub(crate) fn process_batch_update( trader_index % (BLOCK_SIZE as DataIndex) == 0 && trader_index == order.get_trader_index(), ManifestError::WrongIndexHintParams, - &format!("Invalid cancel hint index {}", hinted_index), + &format!("Invalid cancel hint index {}", hinted_cancel_index), )?; dynamic_account.cancel_order_by_index( trader_index, - hinted_index, + hinted_cancel_index, &global_trade_accounts_opts, )?; } diff --git a/programs/manifest/src/state/market.rs b/programs/manifest/src/state/market.rs index acd48e29e..8ee66d3de 100644 --- a/programs/manifest/src/state/market.rs +++ b/programs/manifest/src/state/market.rs @@ -901,7 +901,6 @@ impl, Dynamic: DerefOrBorrowMut<[u8]>> } remove_order_from_tree_and_free(fixed, dynamic, order_index, is_bid)?; - // TODO: Assert that the trader_index is the owner of the order Ok(()) } } diff --git a/programs/manifest/tests/cases/cancel_order.rs b/programs/manifest/tests/cases/cancel_order.rs index c9cad7fa3..9168451aa 100644 --- a/programs/manifest/tests/cases/cancel_order.rs +++ b/programs/manifest/tests/cases/cancel_order.rs @@ -1,11 +1,14 @@ use std::cell::RefMut; +use hypertree::DataIndex; use manifest::{ program::{batch_update::CancelOrderParams, batch_update_instruction}, state::{OrderType, BLOCK_SIZE}, }; use solana_program_test::{tokio, ProgramTestContext}; -use solana_sdk::{instruction::Instruction, signer::Signer, transaction::Transaction}; +use solana_sdk::{ + instruction::Instruction, signature::Keypair, signer::Signer, transaction::Transaction, +}; use crate::{Side, TestFixture, Token, SOL_UNIT_SIZE, USDC_UNIT_SIZE}; @@ -47,8 +50,7 @@ async fn cancel_order_fail_other_trader_order_test() -> anyhow::Result<()> { test_fixture.claim_seat().await?; // Should succeed. It was funded with infinite lamports. - let second_keypair: solana_sdk::signature::Keypair = - test_fixture.second_keypair.insecure_clone(); + let second_keypair: Keypair = test_fixture.second_keypair.insecure_clone(); test_fixture.claim_seat_for_keypair(&second_keypair).await?; test_fixture .deposit_for_keypair(Token::SOL, 2 * SOL_UNIT_SIZE, &second_keypair) @@ -67,6 +69,19 @@ async fn cancel_order_fail_other_trader_order_test() -> anyhow::Result<()> { assert!(test_fixture.cancel_order(0).await.is_err()); + assert!(test_fixture + .batch_update_for_keypair( + None, + vec![CancelOrderParams::new_with_hint( + 0, + Some((BLOCK_SIZE * 2) as DataIndex) + )], + vec![], + &test_fixture.payer_keypair() + ) + .await + .is_err()); + Ok(()) }