diff --git a/crates/ark-contracts/arkchain/src/orderbook.cairo b/crates/ark-contracts/arkchain/src/orderbook.cairo index c6c0814e9..afc4ba1c6 100644 --- a/crates/ark-contracts/arkchain/src/orderbook.cairo +++ b/crates/ark-contracts/arkchain/src/orderbook.cairo @@ -5,7 +5,7 @@ //! and internal functions. The primary functionalities include broker whitelisting, order management //! (creation, cancellation, execution), and order queries. -use arkchain::order::types::ExecutionInfo; +use arkchain::order::types::{ExecutionInfo, OrderType, OrderStatus}; use arkchain::order::order_v1::OrderV1; use arkchain::crypto::signer::{SignInfo, Signer, SignerValidator}; @@ -292,11 +292,41 @@ mod orderbook { fn cancel_order(ref self: ContractState, order_hash: felt252, signer: Signer) { SignerValidator::verify(order_hash, signer); - // TODO: if cancel an auction check if there are offers if true we can't cancel + + // Check if order exists + + let order_option = order_read::(order_hash); + assert(order_option.is_some(), 'order is not exists'); + let order = order_option.unwrap(); + + // Check order status + let status = match order_status_read(order_hash) { Option::Some(s) => s, Option::None => panic_with_felt252(orderbook_errors::ORDER_NOT_FOUND), }; + + // Check expiration date + let block_ts = starknet::get_block_timestamp(); + assert(block_ts < order.end_date, 'order is expired'); + + // Check the order type + match order_type_read(order_hash) { + Option::Some(order_type) => { + if order_type == OrderType::Listing { + // Set order hash to 0 for listings for the TOKEN_HASH + self.token_listings.write(order.compute_token_hash(), 0); + } else if order_type == OrderType::Auction { + // Set to 0 the order_hash for the TOKEN_HASH + self.auctions.write(order.compute_token_hash(), (0, 0, 0)); + } + }, + Option::None => panic_with_felt252(orderbook_errors::ORDER_NOT_FOUND), + }; + + // Cancel order + order_status_write(order_hash, OrderStatus::CancelledUser); + self.emit(OrderCancelled { order_hash, reason: OrderStatus::CancelledUser.into() }); } fn fullfil_order( diff --git a/crates/ark-contracts/arkchain/tests/lib.cairo b/crates/ark-contracts/arkchain/tests/lib.cairo index a975c06bb..916e64b81 100644 --- a/crates/ark-contracts/arkchain/tests/lib.cairo +++ b/crates/ark-contracts/arkchain/tests/lib.cairo @@ -14,4 +14,3 @@ mod unit { mod test_orderbook; } -mod test_orderbook; diff --git a/crates/ark-contracts/arkchain/tests/test_orderbook.cairo b/crates/ark-contracts/arkchain/tests/test_orderbook.cairo deleted file mode 100644 index b3ac0135a..000000000 --- a/crates/ark-contracts/arkchain/tests/test_orderbook.cairo +++ /dev/null @@ -1,120 +0,0 @@ -use core::debug::PrintTrait; -use core::option::OptionTrait; -use arkchain::orderbook::orderbook; -use arkchain::order::order_v1::OrderV1; -use arkchain::order::types::RouteType; -use core::traits::Into; -use core::traits::TryInto; -use arkchain::order::types::OrderType; -use arkchain::order::database::{order_read, order_status_read, order_write}; -use arkchain::order::types::OrderStatus; -use snforge_std::{ - declare, ContractClassTrait, spy_events, EventSpy, EventFetcher, EventAssertions, Event, SpyOn, - test_address -}; -use array::ArrayTrait; - -const ORDER_VERSION_V1: felt252 = 'v1'; - -#[test] -fn test_create_offer() { - let offer_order = get_offer_order(); - let order_hash = '123'; - - let contract_address = test_address(); - let mut state = orderbook::contract_state_for_testing(); - let mut spy = spy_events(SpyOn::One(contract_address)); - - orderbook::InternalFunctions::_create_offer( - ref state, offer_order, OrderType::Offer, order_hash - ); - - let order_option = order_read::(order_hash); - assert(order_option.is_some(), 'storage order'); - let order = order_option.unwrap(); - assert(order.token_address == offer_order.token_address, 'token address does not match'); - - spy - .assert_emitted( - @array![ - ( - contract_address, - orderbook::Event::OrderPlaced( - orderbook::OrderPlaced { - order_hash, - order_version: ORDER_VERSION_V1, - order_type: OrderType::Offer, - order: offer_order, - cancelled_order_hash: Option::None - } - ) - ) - ] - ); -} - -#[test] -fn test_create_collection_offer() { - let contract_address = test_address(); - let mut spy = spy_events(SpyOn::One(contract_address)); - - let mut offer_order = get_offer_order(); - offer_order.token_id = Option::None; - let order_hash = '123'; - - let mut state = orderbook::contract_state_for_testing(); - orderbook::InternalFunctions::_create_collection_offer( - ref state, offer_order, OrderType::CollectionOffer, order_hash - ); - - let order_option = order_read::(order_hash); - assert(order_option.is_some(), 'storage order'); - let order = order_option.unwrap(); - assert(order.token_address == offer_order.token_address, 'token address does not match'); - - spy - .assert_emitted( - @array![ - ( - contract_address, - orderbook::Event::OrderPlaced( - orderbook::OrderPlaced { - order_hash, - order_version: ORDER_VERSION_V1, - order_type: OrderType::CollectionOffer, - order: offer_order, - cancelled_order_hash: Option::None - } - ) - ) - ] - ); -} - -fn get_offer_order() -> OrderV1 { - let data = array![]; - let data_span = data.span(); - OrderV1 { - route: RouteType::Erc20ToErc721.into(), - currency_address: 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 - .try_into() - .unwrap(), - currency_chain_id: 0x534e5f4d41494e.try_into().unwrap(), - salt: 0, - offerer: 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078 - .try_into() - .unwrap(), - token_chain_id: 0x534e5f4d41494e.try_into().unwrap(), - token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 - .try_into() - .unwrap(), - token_id: Option::Some(0), - quantity: 1, - start_amount: 600000000000000000, - end_amount: 0, - start_date: 1699525884797, - end_date: 1702117884797, - broker_id: 123, - additional_data: data_span, - } -} diff --git a/crates/ark-contracts/arkchain/tests/unit/test_orderbook.cairo b/crates/ark-contracts/arkchain/tests/unit/test_orderbook.cairo index 0af11486c..bf3004260 100644 --- a/crates/ark-contracts/arkchain/tests/unit/test_orderbook.cairo +++ b/crates/ark-contracts/arkchain/tests/unit/test_orderbook.cairo @@ -218,3 +218,107 @@ fn test_recreate_listing_same_owner_old_order_expired() { assert(order_status.unwrap() == OrderStatus::Open, 'order status'); assert(order.token_address == order_listing_2.token_address, 'token address does not match'); } + + +#[test] +fn test_create_offer() { + let offer_order = get_offer_order(); + let order_hash = '123'; + + let contract_address = test_address(); + let mut state = orderbook::contract_state_for_testing(); + let mut spy = spy_events(SpyOn::One(contract_address)); + + orderbook::InternalFunctions::_create_offer( + ref state, offer_order, OrderType::Offer, order_hash + ); + + let order_option = order_read::(order_hash); + assert(order_option.is_some(), 'storage order'); + let order = order_option.unwrap(); + assert(order.token_address == offer_order.token_address, 'token address does not match'); + + spy + .assert_emitted( + @array![ + ( + contract_address, + orderbook::Event::OrderPlaced( + orderbook::OrderPlaced { + order_hash, + order_version: ORDER_VERSION_V1, + order_type: OrderType::Offer, + order: offer_order, + cancelled_order_hash: Option::None + } + ) + ) + ] + ); +} + +#[test] +fn test_create_collection_offer() { + let contract_address = test_address(); + let mut spy = spy_events(SpyOn::One(contract_address)); + + let mut offer_order = get_offer_order(); + offer_order.token_id = Option::None; + let order_hash = '123'; + + let mut state = orderbook::contract_state_for_testing(); + orderbook::InternalFunctions::_create_collection_offer( + ref state, offer_order, OrderType::CollectionOffer, order_hash + ); + + let order_option = order_read::(order_hash); + assert(order_option.is_some(), 'storage order'); + let order = order_option.unwrap(); + assert(order.token_address == offer_order.token_address, 'token address does not match'); + + spy + .assert_emitted( + @array![ + ( + contract_address, + orderbook::Event::OrderPlaced( + orderbook::OrderPlaced { + order_hash, + order_version: ORDER_VERSION_V1, + order_type: OrderType::CollectionOffer, + order: offer_order, + cancelled_order_hash: Option::None + } + ) + ) + ] + ); +} + +fn get_offer_order() -> OrderV1 { + let data = array![]; + let data_span = data.span(); + OrderV1 { + route: RouteType::Erc20ToErc721.into(), + currency_address: 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 + .try_into() + .unwrap(), + currency_chain_id: 0x534e5f4d41494e.try_into().unwrap(), + salt: 0, + offerer: 0x00E4769a4d2F7F69C70951A003eBA5c32707Cef3CdfB6B27cA63567f51cdd078 + .try_into() + .unwrap(), + token_chain_id: 0x534e5f4d41494e.try_into().unwrap(), + token_address: 0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672 + .try_into() + .unwrap(), + token_id: Option::Some(1), + quantity: 1, + start_amount: 600000000000000000, + end_amount: 0, + start_date: 1699525884797, + end_date: 1702117884797, + broker_id: 123, + additional_data: data_span, + } +}