From 8bc9ffc943b13e8d44c877e5a757d09823e6f2cb Mon Sep 17 00:00:00 2001 From: tevrat-aksoy Date: Tue, 17 Oct 2023 21:32:46 +0300 Subject: [PATCH 1/4] add liq_handler missing modifiers --- src/exchange/base_order_handler.cairo | 15 + src/exchange/liquidation_handler.cairo | 25 +- tests/exchange/test_liquidation_handler.cairo | 317 +++++++++++------- 3 files changed, 227 insertions(+), 130 deletions(-) diff --git a/src/exchange/base_order_handler.cairo b/src/exchange/base_order_handler.cairo index 988f61e0..07b4eb5f 100644 --- a/src/exchange/base_order_handler.cairo +++ b/src/exchange/base_order_handler.cairo @@ -35,6 +35,8 @@ trait IBaseOrderHandler { swap_handler_address: ContractAddress, referral_storage_address: ContractAddress ); + + fn only_liquidation_keeper(self: @TContractState); } #[starknet::contract] @@ -54,6 +56,10 @@ mod BaseOrderHandler { // Local imports. use super::IBaseOrderHandler; use satoru::role::role_store::{IRoleStoreDispatcher, IRoleStoreDispatcherTrait}; + use satoru::role::role_module::{ + IRoleModuleDispatcher, IRoleModuleDispatcherTrait, RoleModule, IRoleModule + }; + use satoru::data::data_store::{IDataStoreDispatcher, IDataStoreDispatcherTrait}; use satoru::event::event_emitter::{IEventEmitterDispatcher, IEventEmitterDispatcherTrait}; use satoru::oracle::{ @@ -154,6 +160,10 @@ mod BaseOrderHandler { ); self.data_store.write(IDataStoreDispatcher { contract_address: data_store_address }); self.role_store.write(IRoleStoreDispatcher { contract_address: role_store_address }); + + let mut state: RoleModule::ContractState = RoleModule::unsafe_new_contract_state(); + IRoleModule::initialize(ref state, role_store_address,); + self .event_emitter .write(IEventEmitterDispatcher { contract_address: event_emitter_address }); @@ -166,6 +176,11 @@ mod BaseOrderHandler { .referral_storage .write(IReferralStorageDispatcher { contract_address: referral_storage_address }); } + + fn only_liquidation_keeper(self: @ContractState) { + let mut state: RoleModule::ContractState = RoleModule::unsafe_new_contract_state(); + IRoleModule::only_liquidation_keeper(@state); + } } // ************************************************************************* diff --git a/src/exchange/liquidation_handler.cairo b/src/exchange/liquidation_handler.cairo index ed9ff523..508a379d 100644 --- a/src/exchange/liquidation_handler.cairo +++ b/src/exchange/liquidation_handler.cairo @@ -41,7 +41,9 @@ mod LiquidationHandler { // Core lib imports. use satoru::exchange::base_order_handler::BaseOrderHandler::{ - event_emitter::InternalContractMemberStateTrait, data_store::InternalContractMemberStateImpl + event_emitter::InternalContractMemberStateTrait, + data_store::InternalContractMemberStateImpl, + oracle::InternalContractMemberStateTrait as OracleStateTrait, }; use starknet::{ContractAddress, get_caller_address, get_contract_address}; @@ -49,6 +51,8 @@ mod LiquidationHandler { // Local imports. use super::ILiquidationHandler; use satoru::role::role_store::{IRoleStoreSafeDispatcher, IRoleStoreSafeDispatcherTrait}; + use satoru::role::role_module::{IRoleModuleDispatcher, IRoleModuleDispatcherTrait}; + use satoru::data::{ data_store::{IDataStoreSafeDispatcher, IDataStoreSafeDispatcherTrait, DataStore}, keys::execute_order_feature_disabled_key @@ -72,6 +76,8 @@ mod LiquidationHandler { use satoru::feature::feature_utils::validate_feature; use satoru::exchange::order_handler::{IOrderHandler, OrderHandler}; use satoru::utils::starknet_utils; + use satoru::utils::global_reentrancy_guard; + // ************************************************************************* // STORAGE @@ -130,9 +136,21 @@ mod LiquidationHandler { is_long: bool, oracle_params: SetPricesParams ) { - let starting_gas: u128 = starknet_utils::sn_gasleft(array![100]); let mut state_base: BaseOrderHandler::ContractState = BaseOrderHandler::unsafe_new_contract_state(); //retrieve BaseOrderHandler state + global_reentrancy_guard::non_reentrant_before(state_base.data_store.read()); + + state_base.only_liquidation_keeper(); + + with_oracle_prices_before( + state_base.oracle.read(), + state_base.data_store.read(), + state_base.event_emitter.read(), + @oracle_params + ); + + let starting_gas: u128 = starknet_utils::sn_gasleft(array![100]); + let key: felt252 = create_liquidation_order( state_base.data_store.read(), state_base.event_emitter.read(), @@ -156,6 +174,9 @@ mod LiquidationHandler { execute_order_feature_disabled_key(get_contract_address(), params.order.order_type) ); order_utils::execute_order(params); + with_oracle_prices_after(state_base.oracle.read()); + + global_reentrancy_guard::non_reentrant_after(state_base.data_store.read()); } } } diff --git a/tests/exchange/test_liquidation_handler.cairo b/tests/exchange/test_liquidation_handler.cairo index 67a34b2c..6023cd1c 100644 --- a/tests/exchange/test_liquidation_handler.cairo +++ b/tests/exchange/test_liquidation_handler.cairo @@ -1,15 +1,19 @@ -use snforge_std::{declare, start_prank, stop_prank, start_roll, ContractClassTrait, ContractClass}; +use snforge_std::{ + declare, start_prank, stop_prank, start_roll, ContractClassTrait, ContractClass, PrintTrait +}; + use satoru::exchange::liquidation_handler::{ LiquidationHandler, ILiquidationHandlerDispatcher, ILiquidationHandler, ILiquidationHandlerDispatcherTrait }; -use starknet::{ContractAddress, contract_address_const, ClassHash, Felt252TryIntoContractAddress}; +use starknet::{ + ContractAddress, contract_address_const, contract_address_to_felt252, ClassHash, + Felt252TryIntoContractAddress +}; use satoru::position::position_utils::get_position_key; -use debug::PrintTrait; use satoru::mock::referral_storage; use traits::Default; use satoru::oracle::oracle_utils::SetPricesParams; -use satoru::data::data_store::{IDataStoreDispatcher, IDataStoreDispatcherTrait, IDataStore}; use satoru::role::role_store::{IRoleStoreDispatcher, IRoleStoreDispatcherTrait}; use satoru::role::role; use satoru::role::role_module::{IRoleModuleDispatcher, IRoleModuleDispatcherTrait}; @@ -22,9 +26,45 @@ use satoru::exchange::base_order_handler::BaseOrderHandler::{ event_emitter::InternalContractMemberStateTrait, data_store::InternalContractMemberStateImpl }; use satoru::event::event_emitter::{IEventEmitterDispatcher}; +use satoru::data::{data_store::{IDataStoreDispatcher, IDataStoreDispatcherTrait}, keys}; +use satoru::oracle::oracle::{Oracle, IOracleDispatcher, IOracleDispatcherTrait}; +use satoru::utils::precision; +use satoru::price::price::Price; +use satoru::oracle::oracle_store::{IOracleStoreDispatcher, IOracleStoreDispatcherTrait}; #[test] -fn given_normal_conditions_when_create_execute_liquidation_then_works() { +#[should_panic(expected: ('unauthorized_access',))] +fn given_unauthorized_access_when_create_execute_liquidation_then_fails() { + // Setup + + let collateral_token: ContractAddress = contract_address_const::<1>(); + let ( + data_store, + liquidation_keeper, + liquidation_handler_address, + liquidation_handler_dispatcher, + _, + role_store, + _ + ) = + _setup(); + let oracle_params = Default::default(); + + // Check that the test function panics when the caller doesn't have the LIQUIDATION_KEEPER role + liquidation_handler_dispatcher + .execute_liquidation( + account: contract_address_const::<'account'>(), + market: contract_address_const::<'market'>(), + collateral_token: collateral_token, + is_long: true, + oracle_params: oracle_params + ); +} + +#[test] +#[should_panic(expected: ('empty price feed multiplier',))] +fn given_empty_price_feed_multiplier_when_create_execute_liquidation_then_fails() { + // Setup let collateral_token: ContractAddress = contract_address_const::<1>(); let ( data_store, @@ -32,18 +72,74 @@ fn given_normal_conditions_when_create_execute_liquidation_then_works() { liquidation_handler_address, liquidation_handler_dispatcher, _, + role_store, + _ ) = _setup(); + + start_prank(role_store.contract_address, admin()); + role_store.grant_role(liquidation_keeper, role::LIQUIDATION_KEEPER); + stop_prank(role_store.contract_address); + start_prank(liquidation_handler_address, liquidation_keeper); + + let token1 = contract_address_const::<'ETH'>(); + let price_feed_tokens1 = contract_address_const::<'price_feed_tokens'>(); + + let oracle_params = mock_set_prices_params(token1); + // Check that execute_liquidation calls with_oracle_prices_before and fails + + liquidation_handler_dispatcher + .execute_liquidation( + account: contract_address_const::<'account'>(), + market: contract_address_const::<'market'>(), + collateral_token: collateral_token, + is_long: true, + oracle_params: oracle_params + ); +} + +#[test] +fn given_normal_conditions_when_create_execute_liquidation_then_works() { + // Setup + + let collateral_token: ContractAddress = contract_address_const::<1>(); + let ( + data_store, + liquidation_keeper, + liquidation_handler_address, + liquidation_handler_dispatcher, + event_emitter, + role_store, + oracle + ) = + _setup(); + + start_prank(role_store.contract_address, admin()); + role_store.grant_role(liquidation_keeper, role::LIQUIDATION_KEEPER); + stop_prank(role_store.contract_address); start_prank(liquidation_handler_address, liquidation_keeper); - //TODO: add test for execute_liquidation - let account = contract_address_const::<'account'>(); - let market = contract_address_const::<'market'>(); - let key: felt252 = get_position_key(account, market, collateral_token, true); - let mut position: Position = create_new_position( - key, account, market, collateral_token, is_long: true, position_no: 1 - ); - data_store.set_position(key, position); + let token1 = contract_address_const::<'ETH'>(); + let token2 = contract_address_const::<'BTC'>(); + + // Set price feed multiplier + data_store.set_u128(keys::price_feed_multiplier_key(token1), precision::FLOAT_PRECISION); + data_store.set_u128(keys::price_feed_multiplier_key(token2), precision::FLOAT_PRECISION); + data_store.set_u128(keys::max_oracle_ref_price_deviation_factor(), precision::FLOAT_PRECISION); + + let oracle_params2 = mock_set_prices_params(token2); + 'set_prices'.print(); + start_prank(oracle.contract_address, admin()); + oracle.set_prices(data_store, event_emitter, oracle_params2); + stop_prank(oracle.contract_address); + + 'get_primary_price'.print(); + let price = oracle.get_primary_price(token2); + price.min.print(); + price.max.print(); + + let oracle_params = mock_set_prices_params(token1); + 'execute_liquidation'.print(); liquidation_handler_dispatcher .execute_liquidation( @@ -51,64 +147,54 @@ fn given_normal_conditions_when_create_execute_liquidation_then_works() { market: contract_address_const::<'market'>(), collateral_token: collateral_token, is_long: true, - oracle_params: Default::default() + oracle_params: oracle_params ); + 'execute_liquidation2'.print(); +} + + +// ********************************************************************************************* +// * SETUP * +// ********************************************************************************************* + +fn mock_set_prices_params(token: ContractAddress) -> SetPricesParams { + SetPricesParams { + signer_info: 1, + tokens: array![token], + compacted_min_oracle_block_numbers: array![10,], + compacted_max_oracle_block_numbers: array![20], + compacted_oracle_timestamps: array![1000,], + compacted_decimals: array![18], + compacted_min_prices: array![1700,], + compacted_min_prices_indexes: array![0,], + compacted_max_prices: array![1750], + compacted_max_prices_indexes: array![0,], + signatures: array![1, 2, 3], + price_feed_tokens: array![token] + } +} + + +fn admin() -> ContractAddress { + contract_address_const::<'caller'>() } -// TODO: uncomment this test after https://github.com/foundry-rs/starknet-foundry/issues/659 is merged -// #[test] -// fn given_normal_conditions_when_create_liquidation_order_works() { -// let collateral_token: ContractAddress = contract_address_const::<1>(); -// let ( -// data_store, -// liquidation_keeper, -// liquidation_handler_address, -// liquidation_handler_dispatcher, -// event_emitter -// ) = -// _setup(); -// start_prank(liquidation_handler_address, liquidation_keeper); -// start_roll(liquidation_keeper, 1); -// let account = contract_address_const::<'account'>(); -// let market = contract_address_const::<'market'>(); -// let is_long = true; -// let key: felt252 = get_position_key(account, market, collateral_token, true); -// let mut position: Position = create_new_position( -// key, account, market, collateral_token, is_long, position_no: 1 -// ); - -// data_store.set_position(key, position); - -// let key: felt252 = create_liquidation_order( -// data_store, event_emitter, account, market, collateral_token, is_long -// ); - -// let order = data_store.get_order(key).expect('order should be present'); -// assert(order.order_type == OrderType::Liquidation, 'wrong order type'); -// } fn deploy_data_store(role_store_address: ContractAddress) -> ContractAddress { let contract = declare('DataStore'); - let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'data_store'>(); - start_prank(deployed_contract_address, caller_address); + start_prank(deployed_contract_address, admin()); let constructor_calldata = array![role_store_address.into()]; contract.deploy_at(@constructor_calldata, deployed_contract_address).unwrap() } -fn deploy_role_store() -> ContractAddress { - let contract = declare('RoleStore'); - let caller_address: ContractAddress = contract_address_const::<'caller'>(); - let deployed_contract_address = contract_address_const::<'role_store'>(); - start_prank(deployed_contract_address, caller_address); - contract.deploy_at(@array![], deployed_contract_address).unwrap() -} fn deploy_event_emitter() -> ContractAddress { let contract = declare('EventEmitter'); - let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'event_emitter'>(); - start_prank(deployed_contract_address, caller_address); + start_prank(deployed_contract_address, admin()); contract.deploy_at(@array![], deployed_contract_address).unwrap() } @@ -116,9 +202,9 @@ fn deploy_order_vault( data_store_address: ContractAddress, role_store_address: ContractAddress ) -> ContractAddress { let contract = declare('OrderVault'); - let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'order_vault'>(); - start_prank(deployed_contract_address, caller_address); + start_prank(deployed_contract_address, admin()); contract .deploy_at( @array![data_store_address.into(), role_store_address.into()], deployed_contract_address @@ -135,9 +221,9 @@ fn deploy_liquidation_handler( oracle_address: ContractAddress ) -> ContractAddress { let contract = declare('LiquidationHandler'); - let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'liquidation_handler'>(); - start_prank(deployed_contract_address, caller_address); + start_prank(deployed_contract_address, admin()); contract .deploy_at( @array![ @@ -160,9 +246,9 @@ fn deploy_oracle( pragma_address: ContractAddress ) -> ContractAddress { let contract = declare('Oracle'); - let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'oracle'>(); - start_prank(deployed_contract_address, caller_address); + start_prank(deployed_contract_address, admin()); contract .deploy_at( @array![role_store_address.into(), oracle_store_address.into(), pragma_address.into()], @@ -175,17 +261,17 @@ fn deploy_swap_handler( role_store_address: ContractAddress, data_store_address: ContractAddress ) -> ContractAddress { let contract = declare('SwapHandler'); - let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'swap_handler'>(); - start_prank(deployed_contract_address, caller_address); + start_prank(deployed_contract_address, admin()); contract.deploy_at(@array![role_store_address.into()], deployed_contract_address).unwrap() } fn deploy_referral_storage() -> ContractAddress { let contract = declare('ReferralStorage'); - let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'referral_storage'>(); - start_prank(deployed_contract_address, caller_address); + start_prank(deployed_contract_address, admin()); contract.deploy_at(@array![], deployed_contract_address).unwrap() } @@ -193,9 +279,9 @@ fn deploy_oracle_store( role_store_address: ContractAddress, event_emitter_address: ContractAddress, ) -> ContractAddress { let contract = declare('OracleStore'); - let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'oracle_store'>(); - start_prank(deployed_contract_address, caller_address); + start_prank(deployed_contract_address, admin()); contract .deploy_at( @array![role_store_address.into(), event_emitter_address.into()], @@ -204,15 +290,19 @@ fn deploy_oracle_store( .unwrap() } -fn deploy_role_module(role_store_address: ContractAddress) -> IRoleModuleDispatcher { - let contract = declare('RoleModule'); - let caller_address: ContractAddress = contract_address_const::<'caller'>(); - let deployed_contract_address = contract_address_const::<'role_module'>(); - start_prank(deployed_contract_address, caller_address); - let role_module_address = contract - .deploy_at(@array![role_store_address.into()], deployed_contract_address) - .unwrap(); - IRoleModuleDispatcher { contract_address: role_module_address } + +fn deploy_role_store() -> ContractAddress { + let contract = declare('RoleStore'); + let deployed_contract_address: ContractAddress = contract_address_const::<'role_store'>(); + start_prank(deployed_contract_address, admin()); + contract.deploy_at(@array![], deployed_contract_address).unwrap() +} + +fn deploy_price_feed() -> ContractAddress { + let contract = declare('PriceFeed'); + let deployed_contract_address: ContractAddress = contract_address_const::<'price_feed'>(); + start_prank(deployed_contract_address, admin()); + contract.deploy_at(@array![], deployed_contract_address).unwrap() } fn _setup() -> ( @@ -220,12 +310,14 @@ fn _setup() -> ( ContractAddress, ContractAddress, ILiquidationHandlerDispatcher, - IEventEmitterDispatcher + IEventEmitterDispatcher, + IRoleStoreDispatcher, + IOracleDispatcher ) { - let caller_address: ContractAddress = contract_address_const::<'caller'>(); let liquidation_keeper: ContractAddress = 0x2233.try_into().unwrap(); let role_store_address = deploy_role_store(); let role_store = IRoleStoreDispatcher { contract_address: role_store_address }; + let data_store_address = deploy_data_store(role_store_address); let data_store = IDataStoreDispatcher { contract_address: data_store_address }; let event_emitter_address = deploy_event_emitter(); @@ -233,10 +325,9 @@ fn _setup() -> ( let order_vault_address = deploy_order_vault(data_store_address, role_store_address); let swap_handler_address = deploy_swap_handler(role_store_address, data_store_address); let oracle_store_address = deploy_oracle_store(role_store_address, event_emitter_address); - let oracle_address = deploy_oracle( - role_store_address, oracle_store_address, contract_address_const::<'pragma'>() - ); - //let referral_storage_address = deploy_referral_storage(); + let price_feed = deploy_price_feed(); + let oracle_address = deploy_oracle(role_store_address, oracle_store_address, price_feed); + let liquidation_handler_address = deploy_liquidation_handler( role_store_address, data_store_address, @@ -248,56 +339,26 @@ fn _setup() -> ( let liquidation_handler_dispatcher = ILiquidationHandlerDispatcher { contract_address: liquidation_handler_address }; - let role_module = deploy_role_module(role_store_address); - start_prank(role_store_address, caller_address); - role_store.grant_role(caller_address, role::CONTROLLER); - role_store.grant_role(liquidation_keeper, role::LIQUIDATION_KEEPER); - role_store.grant_role(liquidation_keeper, role::ORDER_KEEPER); - role_store.grant_role(liquidation_handler_address, role::FROZEN_ORDER_KEEPER); + + let oracle_store = IOracleStoreDispatcher { contract_address: oracle_store_address }; + start_prank(oracle_store_address, admin()); + oracle_store.add_signer(contract_address_const::<'signer'>()); + stop_prank(oracle_store_address); + + start_prank(role_store.contract_address, admin()); role_store.grant_role(liquidation_handler_address, role::CONTROLLER); - start_prank(data_store_address, caller_address); + role_store.grant_role(admin(), role::CONTROLLER); + stop_prank(role_store.contract_address); + + start_prank(data_store_address, admin()); + ( data_store, liquidation_keeper, liquidation_handler_address, liquidation_handler_dispatcher, - event_emitter + event_emitter, + role_store, + IOracleDispatcher { contract_address: oracle_address } ) } - -fn create_new_position( - key: felt252, - account: ContractAddress, - market: ContractAddress, - collateral_token: ContractAddress, - is_long: bool, - position_no: u128 -) -> Position { - let size_in_usd = 1000 * position_no; - let size_in_tokens = 1000 * position_no; - let collateral_amount = 1000 * position_no; - let borrowing_factor = 10 * position_no; - let funding_fee_amount_per_size = 10 * position_no; - let long_token_claimable_funding_amount_per_size = 10 * position_no; - let short_token_claimable_funding_amount_per_size = 10 * position_no; - let increased_at_block = 1; - let decreased_at_block = 2; - - // Create an position. - Position { - key, - account, - market, - collateral_token, - size_in_usd, - size_in_tokens, - collateral_amount, - borrowing_factor, - funding_fee_amount_per_size, - long_token_claimable_funding_amount_per_size, - short_token_claimable_funding_amount_per_size, - increased_at_block, - decreased_at_block, - is_long, - } -} From 27870f457211558b2ff649d2b64d9153b809a45e Mon Sep 17 00:00:00 2001 From: tevrat-aksoy Date: Fri, 10 Nov 2023 22:05:45 +0300 Subject: [PATCH 2/4] add mock signers --- src/lib.cairo | 1 + src/mock/mock_account.cairo | 85 ++++++++++++++++ tests/exchange/test_liquidation_handler.cairo | 97 ++++++++++++++----- 3 files changed, 159 insertions(+), 24 deletions(-) create mode 100644 src/mock/mock_account.cairo diff --git a/src/lib.cairo b/src/lib.cairo index 40e06bba..7ab9e116 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -176,6 +176,7 @@ mod mock { mod error; mod governable; mod referral_storage; + mod mock_account; } // `oracle` contains functions related to oracles used by Satoru. diff --git a/src/mock/mock_account.cairo b/src/mock/mock_account.cairo new file mode 100644 index 00000000..89f530a8 --- /dev/null +++ b/src/mock/mock_account.cairo @@ -0,0 +1,85 @@ +//! Mock Account for testing. + +#[starknet::contract] +mod MockAccount { + // ************************************************************************* + // IMPORTS + // ************************************************************************* + + // Core lib imports. + use core::zeroable::Zeroable; + use starknet::{get_caller_address, ContractAddress}; + use result::ResultTrait; + + // Local imports. + use satoru::oracle::{ + interfaces::account::{IAccount, IAccountDispatcher, IAccountDispatcherTrait} + }; + + + // ************************************************************************* + // STORAGE + // ************************************************************************* + #[storage] + struct Storage { + owner: felt252, + } + + // ************************************************************************* + // EXTERNAL FUNCTIONS + // ************************************************************************* + #[external(v0)] + impl MockAccount of IAccount { + fn __validate_declare__(self: @ContractState, class_hash: felt252) -> felt252 { + 1 + } + fn __validate_deploy__( + self: @ContractState, + class_hash: felt252, + contract_address_salt: felt252, + owner: felt252, + guardian: felt252 + ) -> felt252 { + 1 + } + + fn change_owner( + ref self: ContractState, new_owner: felt252, signature_r: felt252, signature_s: felt252 + ) { + self.owner.write(new_owner); + } + fn change_guardian(ref self: ContractState, new_guardian: felt252) {} + + + fn change_guardian_backup(ref self: ContractState, new_guardian_backup: felt252) {} + + + fn trigger_escape_owner(ref self: ContractState, new_owner: felt252) {} + + fn trigger_escape_guardian(ref self: ContractState, new_guardian: felt252) {} + + fn escape_owner(ref self: ContractState) {} + + fn escape_guardian(ref self: ContractState) {} + + fn cancel_escape(ref self: ContractState) {} + fn get_owner(self: @ContractState) -> felt252 { + self.owner.read() + } + fn get_guardian(self: @ContractState) -> felt252 { + 1 + } + fn get_guardian_backup(self: @ContractState) -> felt252 { + 1 + } + fn get_name(self: @ContractState) -> felt252 { + 1 + } + fn get_guardian_escape_attempts(self: @ContractState) -> u32 { + 1 + } + fn get_owner_escape_attempts(self: @ContractState) -> u32 { + 1 + } + } +} diff --git a/tests/exchange/test_liquidation_handler.cairo b/tests/exchange/test_liquidation_handler.cairo index 6023cd1c..92f3530a 100644 --- a/tests/exchange/test_liquidation_handler.cairo +++ b/tests/exchange/test_liquidation_handler.cairo @@ -31,6 +31,10 @@ use satoru::oracle::oracle::{Oracle, IOracleDispatcher, IOracleDispatcherTrait}; use satoru::utils::precision; use satoru::price::price::Price; use satoru::oracle::oracle_store::{IOracleStoreDispatcher, IOracleStoreDispatcherTrait}; +use satoru::oracle::{interfaces::account::{IAccount, IAccountDispatcher, IAccountDispatcherTrait}}; +use satoru::market::market::{Market}; + +const max_u128: u128 = 340282366920938463463374607431768211455; #[test] #[should_panic(expected: ('unauthorized_access',))] @@ -45,6 +49,8 @@ fn given_unauthorized_access_when_create_execute_liquidation_then_fails() { liquidation_handler_dispatcher, _, role_store, + _, + _, _ ) = _setup(); @@ -62,7 +68,7 @@ fn given_unauthorized_access_when_create_execute_liquidation_then_fails() { } #[test] -#[should_panic(expected: ('empty price feed multiplier',))] +#[should_panic(expected: ('empty price feed', 'ETH'))] fn given_empty_price_feed_multiplier_when_create_execute_liquidation_then_fails() { // Setup let collateral_token: ContractAddress = contract_address_const::<1>(); @@ -73,6 +79,8 @@ fn given_empty_price_feed_multiplier_when_create_execute_liquidation_then_fails( liquidation_handler_dispatcher, _, role_store, + _, + _, _ ) = _setup(); @@ -85,8 +93,9 @@ fn given_empty_price_feed_multiplier_when_create_execute_liquidation_then_fails( let token1 = contract_address_const::<'ETH'>(); let price_feed_tokens1 = contract_address_const::<'price_feed_tokens'>(); - let oracle_params = mock_set_prices_params(token1); - // Check that execute_liquidation calls with_oracle_prices_before and fails + let mut oracle_params = mock_set_prices_params(token1); + oracle_params.price_feed_tokens= array![token1]; + // Check that execute_liquidation calls 'with_oracle_prices_before' and fails liquidation_handler_dispatcher .execute_liquidation( @@ -102,7 +111,7 @@ fn given_empty_price_feed_multiplier_when_create_execute_liquidation_then_fails( fn given_normal_conditions_when_create_execute_liquidation_then_works() { // Setup - let collateral_token: ContractAddress = contract_address_const::<1>(); + let collateral_token: ContractAddress = contract_address_const::<'USDC'>(); let ( data_store, liquidation_keeper, @@ -110,10 +119,14 @@ fn given_normal_conditions_when_create_execute_liquidation_then_works() { liquidation_handler_dispatcher, event_emitter, role_store, - oracle + oracle, + signer1, + signer2 ) = _setup(); - + let account =contract_address_const::<'account'>(); + + // Grant LIQUIDATION_KEEPER role start_prank(role_store.contract_address, admin()); role_store.grant_role(liquidation_keeper, role::LIQUIDATION_KEEPER); stop_prank(role_store.contract_address); @@ -122,29 +135,44 @@ fn given_normal_conditions_when_create_execute_liquidation_then_works() { let token1 = contract_address_const::<'ETH'>(); let token2 = contract_address_const::<'BTC'>(); + // Use mock account to mattch keys + signer1.change_owner(1221698997303567203808303576674742997327105320284925779268978961645745386877, 0, 0); + signer2.change_owner(1221698997303567203808303576674742997327105320284925779268978961645745386877, 0, 0); + + data_store.set_token_id(token1, 1); + data_store.set_token_id(token2, 2); + // Set price feed multiplier data_store.set_u128(keys::price_feed_multiplier_key(token1), precision::FLOAT_PRECISION); data_store.set_u128(keys::price_feed_multiplier_key(token2), precision::FLOAT_PRECISION); - data_store.set_u128(keys::max_oracle_ref_price_deviation_factor(), precision::FLOAT_PRECISION); + data_store.set_u128(keys::max_oracle_ref_price_deviation_factor(),max_u128 ); + + // + let mut market = Market { + market_token: contract_address_const::<'market'>(), + index_token: collateral_token, + long_token: token1, + short_token: token1, + }; + data_store.set_market(market.market_token, 0, market); - let oracle_params2 = mock_set_prices_params(token2); - 'set_prices'.print(); - start_prank(oracle.contract_address, admin()); - oracle.set_prices(data_store, event_emitter, oracle_params2); - stop_prank(oracle.contract_address); + // Get position key + 'setpos-------'.print(); - 'get_primary_price'.print(); - let price = oracle.get_primary_price(token2); - price.min.print(); - price.max.print(); + let pos_key=get_position_key(account, market.market_token, collateral_token, true); + let mut position:Position= Default::default(); + position.account=account; + position.size_in_usd=precision::FLOAT_PRECISION_SQRT; + position.collateral_token=collateral_token; + position.is_long=true; + data_store.set_position(pos_key, position); let oracle_params = mock_set_prices_params(token1); - 'execute_liquidation'.print(); liquidation_handler_dispatcher .execute_liquidation( - account: contract_address_const::<'account'>(), - market: contract_address_const::<'market'>(), + account:account, + market: market.market_token, collateral_token: collateral_token, is_long: true, oracle_params: oracle_params @@ -169,8 +197,8 @@ fn mock_set_prices_params(token: ContractAddress) -> SetPricesParams { compacted_min_prices_indexes: array![0,], compacted_max_prices: array![1750], compacted_max_prices_indexes: array![0,], - signatures: array![1, 2, 3], - price_feed_tokens: array![token] + signatures: array![array!['signature1', 'signature2'].span()], + price_feed_tokens: Default::default() } } @@ -305,6 +333,17 @@ fn deploy_price_feed() -> ContractAddress { contract.deploy_at(@array![], deployed_contract_address).unwrap() } +fn deploy_signers( + signer1: ContractAddress, signer2: ContractAddress +) -> (ContractAddress, ContractAddress) { + let contract = declare('MockAccount'); + ( + contract.deploy_at(@array![], signer1).unwrap(), + contract.deploy_at(@array![], signer2).unwrap() + ) +} + + fn _setup() -> ( IDataStoreDispatcher, ContractAddress, @@ -312,7 +351,9 @@ fn _setup() -> ( ILiquidationHandlerDispatcher, IEventEmitterDispatcher, IRoleStoreDispatcher, - IOracleDispatcher + IOracleDispatcher, + IAccountDispatcher, + IAccountDispatcher ) { let liquidation_keeper: ContractAddress = 0x2233.try_into().unwrap(); let role_store_address = deploy_role_store(); @@ -341,12 +382,18 @@ fn _setup() -> ( }; let oracle_store = IOracleStoreDispatcher { contract_address: oracle_store_address }; + + let (signer1, signer2) = deploy_signers( + contract_address_const::<'signer1'>(), contract_address_const::<'signer2'>() + ); start_prank(oracle_store_address, admin()); - oracle_store.add_signer(contract_address_const::<'signer'>()); + oracle_store.add_signer(signer1); + oracle_store.add_signer(signer2); stop_prank(oracle_store_address); start_prank(role_store.contract_address, admin()); role_store.grant_role(liquidation_handler_address, role::CONTROLLER); + role_store.grant_role( admin(), role::MARKET_KEEPER); role_store.grant_role(admin(), role::CONTROLLER); stop_prank(role_store.contract_address); @@ -359,6 +406,8 @@ fn _setup() -> ( liquidation_handler_dispatcher, event_emitter, role_store, - IOracleDispatcher { contract_address: oracle_address } + IOracleDispatcher { contract_address: oracle_address }, + IAccountDispatcher { contract_address: signer1 }, + IAccountDispatcher { contract_address: signer2 }, ) } From 13492325d637e11b43695d7a76ee801610eee66d Mon Sep 17 00:00:00 2001 From: tevrat-aksoy Date: Tue, 14 Nov 2023 11:05:44 +0300 Subject: [PATCH 3/4] add new tests --- src/gas/gas_utils.cairo | 2 +- tests/exchange/test_liquidation_handler.cairo | 325 ++++++++++++++++-- 2 files changed, 290 insertions(+), 37 deletions(-) diff --git a/src/gas/gas_utils.cairo b/src/gas/gas_utils.cairo index b7623162..33e2f85b 100644 --- a/src/gas/gas_utils.cairo +++ b/src/gas/gas_utils.cairo @@ -147,7 +147,7 @@ fn pay_execution_fee_order( // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this let reduced_starting_gas = starting_gas - sn_gasleft(array![100]) / 63; - let gas_used = reduced_starting_gas - sn_gasleft(array![100]); + let gas_used = reduced_starting_gas - sn_gasleft(array![0]); // each external call forwards 63/64 of the remaining gas let mut execution_fee_for_keeper = adjust_gas_usage(data_store, gas_used) diff --git a/tests/exchange/test_liquidation_handler.cairo b/tests/exchange/test_liquidation_handler.cairo index 92f3530a..3e41e5a8 100644 --- a/tests/exchange/test_liquidation_handler.cairo +++ b/tests/exchange/test_liquidation_handler.cairo @@ -33,9 +33,10 @@ use satoru::price::price::Price; use satoru::oracle::oracle_store::{IOracleStoreDispatcher, IOracleStoreDispatcherTrait}; use satoru::oracle::{interfaces::account::{IAccount, IAccountDispatcher, IAccountDispatcherTrait}}; use satoru::market::market::{Market}; - +use satoru::nonce::nonce_utils; const max_u128: u128 = 340282366920938463463374607431768211455; + #[test] #[should_panic(expected: ('unauthorized_access',))] fn given_unauthorized_access_when_create_execute_liquidation_then_fails() { @@ -56,6 +57,7 @@ fn given_unauthorized_access_when_create_execute_liquidation_then_fails() { _setup(); let oracle_params = Default::default(); + // Test // Check that the test function panics when the caller doesn't have the LIQUIDATION_KEEPER role liquidation_handler_dispatcher .execute_liquidation( @@ -90,13 +92,17 @@ fn given_empty_price_feed_multiplier_when_create_execute_liquidation_then_fails( stop_prank(role_store.contract_address); start_prank(liquidation_handler_address, liquidation_keeper); + let collateral_token: ContractAddress = contract_address_const::<'USDC'>(); let token1 = contract_address_const::<'ETH'>(); let price_feed_tokens1 = contract_address_const::<'price_feed_tokens'>(); - let mut oracle_params = mock_set_prices_params(token1); - oracle_params.price_feed_tokens= array![token1]; - // Check that execute_liquidation calls 'with_oracle_prices_before' and fails + let price: Price = Default::default(); + + let mut oracle_params = mock_set_prices_params(token1, collateral_token); + oracle_params.price_feed_tokens = array![token1]; + // Test + // Check that execute_liquidation calls 'with_oracle_prices_before' and fails liquidation_handler_dispatcher .execute_liquidation( account: contract_address_const::<'account'>(), @@ -107,11 +113,102 @@ fn given_empty_price_feed_multiplier_when_create_execute_liquidation_then_fails( ); } + #[test] -fn given_normal_conditions_when_create_execute_liquidation_then_works() { +#[should_panic(expected: ('FeatureUtils: disabled feature',))] +fn given_disabled_feature_when_create_execute_liquidation_then_fails() { // Setup + let ( + data_store, + liquidation_keeper, + liquidation_handler_address, + liquidation_handler_dispatcher, + event_emitter, + role_store, + oracle, + signer1, + signer2 + ) = + _setup(); + let account = contract_address_const::<'account'>(); + + // Grant LIQUIDATION_KEEPER role + start_prank(role_store.contract_address, admin()); + role_store.grant_role(liquidation_keeper, role::LIQUIDATION_KEEPER); + stop_prank(role_store.contract_address); + start_prank(liquidation_handler_address, liquidation_keeper); + let collateral_token: ContractAddress = contract_address_const::<'USDC'>(); + let token1 = contract_address_const::<'ETH'>(); + let token2 = contract_address_const::<'BTC'>(); + + // Use mock account to match keys + signer1 + .change_owner( + 1221698997303567203808303576674742997327105320284925779268978961645745386877, 0, 0 + ); + signer2 + .change_owner( + 1221698997303567203808303576674742997327105320284925779268978961645745386877, 0, 0 + ); + + data_store.set_token_id(token1, 1); + data_store.set_token_id(token2, 2); + data_store.set_token_id(collateral_token, 3); + + // Set price feed multiplier + data_store.set_u128(keys::price_feed_multiplier_key(token1), precision::FLOAT_PRECISION); + data_store.set_u128(keys::price_feed_multiplier_key(token2), precision::FLOAT_PRECISION); + data_store + .set_u128(keys::price_feed_multiplier_key(collateral_token), precision::FLOAT_PRECISION); + data_store.set_u128(keys::max_oracle_ref_price_deviation_factor(), max_u128); + + let usdc_price = Price { min: 1000000, max: 1000000 }; + let eth_price = Price { min: 17500000000000, max: 17500000000000 }; + let mut market = Market { + market_token: contract_address_const::<'market'>(), + index_token: collateral_token, + long_token: token1, + short_token: token1, + }; + data_store.set_market(market.market_token, 0, market); + + // Set position + let pos_key = get_position_key(account, market.market_token, collateral_token, true); + let mut position: Position = Default::default(); + position.account = account; + position.size_in_usd = precision::FLOAT_PRECISION_SQRT; + position.collateral_token = collateral_token; + position.is_long = true; + position.size_in_tokens = 100; + data_store.set_position(pos_key, position); + + // Disable feature + let key = keys::execute_order_feature_disabled_key( + liquidation_handler_address, OrderType::Liquidation + ); + data_store.set_bool(key, true); + + let oracle_params = mock_set_prices_params(token1, collateral_token); + + // Test + liquidation_handler_dispatcher + .execute_liquidation( + account: account, + market: market.market_token, + collateral_token: collateral_token, + is_long: true, + oracle_params: oracle_params + ); +} + + +#[test] +#[should_panic(expected: ('negative open interest',))] +fn given_negative_open_interest_when_create_execute_liquidation_then_fails() { + // Setup + let ( data_store, liquidation_keeper, @@ -124,60 +221,183 @@ fn given_normal_conditions_when_create_execute_liquidation_then_works() { signer2 ) = _setup(); - let account =contract_address_const::<'account'>(); - + let account = contract_address_const::<'account'>(); + // Grant LIQUIDATION_KEEPER role start_prank(role_store.contract_address, admin()); role_store.grant_role(liquidation_keeper, role::LIQUIDATION_KEEPER); stop_prank(role_store.contract_address); start_prank(liquidation_handler_address, liquidation_keeper); + let collateral_token: ContractAddress = contract_address_const::<'USDC'>(); let token1 = contract_address_const::<'ETH'>(); let token2 = contract_address_const::<'BTC'>(); - // Use mock account to mattch keys - signer1.change_owner(1221698997303567203808303576674742997327105320284925779268978961645745386877, 0, 0); - signer2.change_owner(1221698997303567203808303576674742997327105320284925779268978961645745386877, 0, 0); + // Use mock account to match keys + signer1 + .change_owner( + 1221698997303567203808303576674742997327105320284925779268978961645745386877, 0, 0 + ); + signer2 + .change_owner( + 1221698997303567203808303576674742997327105320284925779268978961645745386877, 0, 0 + ); data_store.set_token_id(token1, 1); data_store.set_token_id(token2, 2); + data_store.set_token_id(collateral_token, 3); // Set price feed multiplier data_store.set_u128(keys::price_feed_multiplier_key(token1), precision::FLOAT_PRECISION); data_store.set_u128(keys::price_feed_multiplier_key(token2), precision::FLOAT_PRECISION); - data_store.set_u128(keys::max_oracle_ref_price_deviation_factor(),max_u128 ); + data_store + .set_u128(keys::price_feed_multiplier_key(collateral_token), precision::FLOAT_PRECISION); + data_store.set_u128(keys::max_oracle_ref_price_deviation_factor(), max_u128); - // + let usdc_price = Price { min: 1000000, max: 1000000 }; + let eth_price = Price { min: 17500000000000, max: 17500000000000 }; let mut market = Market { market_token: contract_address_const::<'market'>(), - index_token: collateral_token, - long_token: token1, - short_token: token1, + index_token: collateral_token, + long_token: token1, + short_token: token1, }; data_store.set_market(market.market_token, 0, market); - // Get position key - 'setpos-------'.print(); + // Set position + let pos_key = get_position_key(account, market.market_token, collateral_token, true); + let mut position: Position = Default::default(); + position.account = account; + position.size_in_usd = precision::FLOAT_PRECISION_SQRT; + position.collateral_token = collateral_token; + position.is_long = true; + position.size_in_tokens = 100; + data_store.set_position(pos_key, position); + + // Set open interest + let interest_key1 = keys::open_interest_key(market.market_token, market.long_token, true); + data_store.set_u128(interest_key1, 1000000000000000000000); + let oracle_params = mock_set_prices_params(token1, collateral_token); + + // Test + liquidation_handler_dispatcher + .execute_liquidation( + account: account, + market: market.market_token, + collateral_token: collateral_token, + is_long: true, + oracle_params: oracle_params + ); +} + + +#[test] +fn given_normal_conditions_when_create_execute_liquidation_then_works() { + // Setup + + let ( + data_store, + liquidation_keeper, + liquidation_handler_address, + liquidation_handler_dispatcher, + event_emitter, + role_store, + oracle, + signer1, + signer2 + ) = + _setup(); + let account = contract_address_const::<'account'>(); + + // Grant LIQUIDATION_KEEPER role + start_prank(role_store.contract_address, admin()); + role_store.grant_role(liquidation_keeper, role::LIQUIDATION_KEEPER); + stop_prank(role_store.contract_address); + start_prank(liquidation_handler_address, liquidation_keeper); + + let (collateral_token, token1, fee_token) = setup_tokens(); + let token2 = contract_address_const::<'BTC'>(); - let pos_key=get_position_key(account, market.market_token, collateral_token, true); - let mut position:Position= Default::default(); - position.account=account; - position.size_in_usd=precision::FLOAT_PRECISION_SQRT; - position.collateral_token=collateral_token; - position.is_long=true; + // Use mock account to match keys + signer1 + .change_owner( + 1221698997303567203808303576674742997327105320284925779268978961645745386877, 0, 0 + ); + signer2 + .change_owner( + 1221698997303567203808303576674742997327105320284925779268978961645745386877, 0, 0 + ); + + data_store.set_token_id(token1, 1); + data_store.set_token_id(token2, 2); + data_store.set_token_id(collateral_token, 3); + + data_store.set_address(keys::fee_token(), fee_token); + + // Set price feed multiplier + data_store.set_u128(keys::price_feed_multiplier_key(token1), precision::FLOAT_PRECISION); + data_store.set_u128(keys::price_feed_multiplier_key(token2), precision::FLOAT_PRECISION); + data_store + .set_u128(keys::price_feed_multiplier_key(collateral_token), precision::FLOAT_PRECISION); + data_store.set_u128(keys::max_oracle_ref_price_deviation_factor(), max_u128); + + let usdc_price = Price { min: 1000000, max: 1000000 }; + let eth_price = Price { min: 17500000000000, max: 17500000000000 }; + let mut market = Market { + market_token: contract_address_const::<'market'>(), + index_token: collateral_token, + long_token: token1, + short_token: token1, + }; + data_store.set_market(market.market_token, 0, market); + + // Set position + let pos_key = get_position_key(account, market.market_token, collateral_token, true); + let mut position: Position = Default::default(); + position.account = account; + position.size_in_usd = precision::FLOAT_PRECISION_SQRT; + position.collateral_token = collateral_token; + position.is_long = true; + position.size_in_tokens = 100; data_store.set_position(pos_key, position); - let oracle_params = mock_set_prices_params(token1); + // Set open interest + let interest_key1 = keys::open_interest_key(market.market_token, market.long_token, true); + data_store.set_u128(interest_key1, 1000000000000000000000); + + let interest_key2 = keys::open_interest_key(market.market_token, collateral_token, true); + data_store.set_u128(interest_key2, 10000000000); + let interest_key3 = keys::open_interest_in_tokens_key( + market.market_token, collateral_token, true + ); + data_store.set_u128(interest_key3, 10000000000); + + let current_nonce = nonce_utils::get_current_nonce(data_store); + + let oracle_params = mock_set_prices_params(token1, collateral_token); + // Test liquidation_handler_dispatcher .execute_liquidation( - account:account, + account: account, market: market.market_token, collateral_token: collateral_token, is_long: true, oracle_params: oracle_params ); - 'execute_liquidation2'.print(); + + // Check 'with_oracle_prices_after' clear the prices + let prices_count = oracle.get_tokens_with_prices_count(); + assert(prices_count == 0, 'invalid prices_count'); + + // Check new order is created and nonce is increased + let last_nonce = nonce_utils::get_current_nonce(data_store); + assert(last_nonce == current_nonce + 1, 'invalid last_nonce'); + + // Check new order removed + let order_key = nonce_utils::compute_key(data_store.contract_address, last_nonce); + let order_by_key = data_store.get_order(order_key); + assert(order_by_key == Default::default(), 'Invalid order by key'); } @@ -185,10 +405,10 @@ fn given_normal_conditions_when_create_execute_liquidation_then_works() { // * SETUP * // ********************************************************************************************* -fn mock_set_prices_params(token: ContractAddress) -> SetPricesParams { +fn mock_set_prices_params(token1: ContractAddress, token2: ContractAddress) -> SetPricesParams { SetPricesParams { signer_info: 1, - tokens: array![token], + tokens: array![token1], compacted_min_oracle_block_numbers: array![10,], compacted_max_oracle_block_numbers: array![20], compacted_oracle_timestamps: array![1000,], @@ -198,7 +418,7 @@ fn mock_set_prices_params(token: ContractAddress) -> SetPricesParams { compacted_max_prices: array![1750], compacted_max_prices_indexes: array![0,], signatures: array![array!['signature1', 'signature2'].span()], - price_feed_tokens: Default::default() + price_feed_tokens: array![token2], } } @@ -246,7 +466,8 @@ fn deploy_liquidation_handler( event_emitter_address: ContractAddress, order_vault_address: ContractAddress, swap_handler_address: ContractAddress, - oracle_address: ContractAddress + oracle_address: ContractAddress, + ref_storage_address: ContractAddress ) -> ContractAddress { let contract = declare('LiquidationHandler'); @@ -261,7 +482,7 @@ fn deploy_liquidation_handler( order_vault_address.into(), oracle_address.into(), swap_handler_address.into(), - Default::default() + ref_storage_address.into() ], deployed_contract_address ) @@ -295,12 +516,11 @@ fn deploy_swap_handler( contract.deploy_at(@array![role_store_address.into()], deployed_contract_address).unwrap() } -fn deploy_referral_storage() -> ContractAddress { +fn deploy_referral_storage(event_emitter: ContractAddress) -> ContractAddress { let contract = declare('ReferralStorage'); - let deployed_contract_address = contract_address_const::<'referral_storage'>(); start_prank(deployed_contract_address, admin()); - contract.deploy_at(@array![], deployed_contract_address).unwrap() + contract.deploy_at(@array![event_emitter.into()], deployed_contract_address).unwrap() } fn deploy_oracle_store( @@ -344,6 +564,37 @@ fn deploy_signers( } +fn setup_tokens() -> (ContractAddress, ContractAddress, ContractAddress) { + let contract = declare('ERC20'); + let deployed_contract_address: ContractAddress = contract_address_const::<'USDC'>(); + let mut constructor_calldata = array![ + 'USDC', 'USDC', 10000000000000000000000000000, 0, admin().into() + ]; + + let usdc_address = contract + .deploy_at(@constructor_calldata, deployed_contract_address) + .unwrap(); + + let deployed_contract_address2: ContractAddress = contract_address_const::<'ETH'>(); + let constructor_calldata2 = array![ + 'ETH', 'ETH', 100000000000000000000000000000, 0, admin().into() + ]; + let eth_address = contract + .deploy_at(@constructor_calldata2, deployed_contract_address2) + .unwrap(); + + let deployed_contract_address3: ContractAddress = contract_address_const::<'FEE'>(); + let constructor_calldata3 = array![ + 'FEE', 'FEE', 100000000000000000000000000000, 0, admin().into() + ]; + let fee_address = contract + .deploy_at(@constructor_calldata3, deployed_contract_address3) + .unwrap(); + + (usdc_address, eth_address, fee_address) +} + + fn _setup() -> ( IDataStoreDispatcher, ContractAddress, @@ -369,13 +620,15 @@ fn _setup() -> ( let price_feed = deploy_price_feed(); let oracle_address = deploy_oracle(role_store_address, oracle_store_address, price_feed); + let ref_storage_address = deploy_referral_storage(event_emitter_address); let liquidation_handler_address = deploy_liquidation_handler( role_store_address, data_store_address, event_emitter_address, order_vault_address, swap_handler_address, - oracle_address + oracle_address, + ref_storage_address ); let liquidation_handler_dispatcher = ILiquidationHandlerDispatcher { contract_address: liquidation_handler_address @@ -393,7 +646,7 @@ fn _setup() -> ( start_prank(role_store.contract_address, admin()); role_store.grant_role(liquidation_handler_address, role::CONTROLLER); - role_store.grant_role( admin(), role::MARKET_KEEPER); + role_store.grant_role(admin(), role::MARKET_KEEPER); role_store.grant_role(admin(), role::CONTROLLER); stop_prank(role_store.contract_address); From c5354902dd17997a0ff6b24971a6204b4e1c07c0 Mon Sep 17 00:00:00 2001 From: tevrat-aksoy Date: Wed, 22 Nov 2023 21:57:25 +0300 Subject: [PATCH 4/4] fix imports --- src/exchange/base_order_handler.cairo | 10 ------ src/exchange/liquidation_handler.cairo | 32 +++++++++++-------- tests/exchange/test_liquidation_handler.cairo | 32 ++++++++++++------- 3 files changed, 39 insertions(+), 35 deletions(-) diff --git a/src/exchange/base_order_handler.cairo b/src/exchange/base_order_handler.cairo index f7c6736b..406e11c6 100644 --- a/src/exchange/base_order_handler.cairo +++ b/src/exchange/base_order_handler.cairo @@ -35,8 +35,6 @@ trait IBaseOrderHandler { swap_handler_address: ContractAddress, referral_storage_address: ContractAddress ); - - fn only_liquidation_keeper(self: @TContractState); } #[starknet::contract] @@ -161,9 +159,6 @@ mod BaseOrderHandler { self.data_store.write(IDataStoreDispatcher { contract_address: data_store_address }); self.role_store.write(IRoleStoreDispatcher { contract_address: role_store_address }); - let mut state: RoleModule::ContractState = RoleModule::unsafe_new_contract_state(); - IRoleModule::initialize(ref state, role_store_address,); - self .event_emitter .write(IEventEmitterDispatcher { contract_address: event_emitter_address }); @@ -176,11 +171,6 @@ mod BaseOrderHandler { .referral_storage .write(IReferralStorageDispatcher { contract_address: referral_storage_address }); } - - fn only_liquidation_keeper(self: @ContractState) { - let mut state: RoleModule::ContractState = RoleModule::unsafe_new_contract_state(); - IRoleModule::only_liquidation_keeper(@state); - } } // ************************************************************************* diff --git a/src/exchange/liquidation_handler.cairo b/src/exchange/liquidation_handler.cairo index bcd1e776..b6053df3 100644 --- a/src/exchange/liquidation_handler.cairo +++ b/src/exchange/liquidation_handler.cairo @@ -40,18 +40,14 @@ mod LiquidationHandler { // ************************************************************************* // Core lib imports. - use satoru::exchange::base_order_handler::BaseOrderHandler::{ - event_emitter::InternalContractMemberStateTrait, - data_store::InternalContractMemberStateImpl, - oracle::InternalContractMemberStateTrait as OracleStateTrait, - }; + use starknet::{ContractAddress, get_caller_address, get_contract_address}; // Local imports. use super::ILiquidationHandler; use satoru::role::role_store::{IRoleStoreSafeDispatcher, IRoleStoreSafeDispatcherTrait}; - use satoru::role::role_module::{IRoleModuleDispatcher, IRoleModuleDispatcherTrait}; + use satoru::role::role_module::{RoleModule, IRoleModule}; use satoru::data::{ data_store::{IDataStoreSafeDispatcher, IDataStoreSafeDispatcherTrait, DataStore}, @@ -69,14 +65,20 @@ mod LiquidationHandler { }; use satoru::swap::swap_handler::{ISwapHandlerDispatcher, ISwapHandlerDispatcherTrait}; use satoru::market::market::Market; - use satoru::exchange::base_order_handler::{IBaseOrderHandler, BaseOrderHandler}; + use satoru::exchange::{ + order_handler::{IOrderHandler, OrderHandler}, + base_order_handler::{IBaseOrderHandler, BaseOrderHandler} + }; + + use satoru::liquidation::liquidation_utils::create_liquidation_order; - use satoru::exchange::order_handler; use satoru::feature::feature_utils::validate_feature; - use satoru::exchange::order_handler::{IOrderHandler, OrderHandler}; - use satoru::utils::starknet_utils; - use satoru::utils::global_reentrancy_guard; - + use satoru::utils::{starknet_utils, global_reentrancy_guard}; + use satoru::exchange::base_order_handler::BaseOrderHandler::{ + event_emitter::InternalContractMemberStateTrait, + data_store::InternalContractMemberStateImpl, + oracle::InternalContractMemberStateTrait as OracleStateTrait, + }; // ************************************************************************* // STORAGE @@ -119,6 +121,9 @@ mod LiquidationHandler { swap_handler_address, referral_storage_address ); + + let mut state: RoleModule::ContractState = RoleModule::unsafe_new_contract_state(); + IRoleModule::initialize(ref state, role_store_address,); } @@ -141,7 +146,8 @@ mod LiquidationHandler { BaseOrderHandler::unsafe_new_contract_state(); //retrieve BaseOrderHandler state global_reentrancy_guard::non_reentrant_before(state_base.data_store.read()); - state_base.only_liquidation_keeper(); + let mut role_state: RoleModule::ContractState = RoleModule::unsafe_new_contract_state(); + IRoleModule::only_liquidation_keeper(@role_state); with_oracle_prices_before( state_base.oracle.read(), diff --git a/tests/exchange/test_liquidation_handler.cairo b/tests/exchange/test_liquidation_handler.cairo index 3e41e5a8..674bcc8f 100644 --- a/tests/exchange/test_liquidation_handler.cairo +++ b/tests/exchange/test_liquidation_handler.cairo @@ -10,28 +10,36 @@ use starknet::{ ContractAddress, contract_address_const, contract_address_to_felt252, ClassHash, Felt252TryIntoContractAddress }; -use satoru::position::position_utils::get_position_key; use satoru::mock::referral_storage; use traits::Default; -use satoru::oracle::oracle_utils::SetPricesParams; -use satoru::role::role_store::{IRoleStoreDispatcher, IRoleStoreDispatcherTrait}; -use satoru::role::role; -use satoru::role::role_module::{IRoleModuleDispatcher, IRoleModuleDispatcherTrait}; + +use satoru::role::{ + role, role_store::{IRoleStoreDispatcher, IRoleStoreDispatcherTrait}, + role_module::{IRoleModuleDispatcher, IRoleModuleDispatcherTrait} +}; + use satoru::order::order::{Order, OrderType, OrderTrait, DecreasePositionSwapType}; use satoru::utils::span32::{Span32, Array32Trait}; -use satoru::position::position::Position; +use satoru::position::{position::Position, position_utils::get_position_key}; use satoru::liquidation::liquidation_utils::create_liquidation_order; -use satoru::exchange::base_order_handler::{IBaseOrderHandler, BaseOrderHandler}; -use satoru::exchange::base_order_handler::BaseOrderHandler::{ - event_emitter::InternalContractMemberStateTrait, data_store::InternalContractMemberStateImpl +use satoru::exchange::base_order_handler::{ + IBaseOrderHandler, + BaseOrderHandler::{ + event_emitter::InternalContractMemberStateTrait, data_store::InternalContractMemberStateImpl + } }; + use satoru::event::event_emitter::{IEventEmitterDispatcher}; use satoru::data::{data_store::{IDataStoreDispatcher, IDataStoreDispatcherTrait}, keys}; -use satoru::oracle::oracle::{Oracle, IOracleDispatcher, IOracleDispatcherTrait}; +use satoru::oracle::{ + oracle::{Oracle, IOracleDispatcher, IOracleDispatcherTrait}, + oracle_store::{IOracleStoreDispatcher, IOracleStoreDispatcherTrait}, + interfaces::account::{IAccount, IAccountDispatcher, IAccountDispatcherTrait}, + oracle_utils::SetPricesParams +}; + use satoru::utils::precision; use satoru::price::price::Price; -use satoru::oracle::oracle_store::{IOracleStoreDispatcher, IOracleStoreDispatcherTrait}; -use satoru::oracle::{interfaces::account::{IAccount, IAccountDispatcher, IAccountDispatcherTrait}}; use satoru::market::market::{Market}; use satoru::nonce::nonce_utils; const max_u128: u128 = 340282366920938463463374607431768211455;