diff --git a/scripts/app/deployApp.ts b/scripts/app/deployApp.ts index 76b889f7..df67e24f 100644 --- a/scripts/app/deployApp.ts +++ b/scripts/app/deployApp.ts @@ -134,6 +134,51 @@ async function deploy() { }) console.log("ReferralStorage Deployed.") + console.log("Deploying IncreaseOrderUtils") + const compiledIncreaseOrderUtilsCasm = json.parse(fs.readFileSync( "./target/dev/satoru_IncreaseOrderUtils.compiled_contract_class.json").toString( "ascii")) + const compiledIncreaseOrderUtilsSierra = json.parse(fs.readFileSync( "./target/dev/satoru_IncreaseOrderUtils.contract_class.json").toString( "ascii")) + const increaseOrderUtilsCallData: CallData = new CallData(compiledIncreaseOrderUtilsSierra.abi) + const increaseOrderUtilsConstructor: Calldata = increaseOrderUtilsCallData.compile("constructor", {}) + const deployIncreaseOrderUtilsResponse = await account0.declareAndDeploy({ + contract: compiledIncreaseOrderUtilsSierra, + casm: compiledIncreaseOrderUtilsCasm, + }) + + console.log("Deploying DecreaseOrderUtils") + const compiledDecreaseOrderUtilsCasm = json.parse(fs.readFileSync( "./target/dev/satoru_DecreaseOrderUtils.compiled_contract_class.json").toString( "ascii")) + const compiledDecreaseOrderUtilsSierra = json.parse(fs.readFileSync( "./target/dev/satoru_DecreaseOrderUtils.contract_class.json").toString( "ascii")) + const decreaseOrderUtilsCallData: CallData = new CallData(compiledDecreaseOrderUtilsSierra.abi) + const decreaseOrderUtilsConstructor: Calldata = decreaseOrderUtilsCallData.compile("constructor", {}) + const deployDecreaseOrderUtilsResponse = await account0.declareAndDeploy({ + contract: compiledDecreaseOrderUtilsSierra, + casm: compiledDecreaseOrderUtilsCasm, + }) + + console.log("Deploying SwapOrderUtils") + const compiledSwapOrderUtilsCasm = json.parse(fs.readFileSync( "./target/dev/satoru_SwapOrderUtils.compiled_contract_class.json").toString( "ascii")) + const compiledSwapOrderUtilsSierra = json.parse(fs.readFileSync( "./target/dev/satoru_SwapOrderUtils.contract_class.json").toString( "ascii")) + const swapOrderUtilsCallData: CallData = new CallData(compiledSwapOrderUtilsSierra.abi) + const swapOrderUtilsConstructor: Calldata = swapOrderUtilsCallData.compile("constructor", {}) + const deploySwapOrderUtilsResponse = await account0.declareAndDeploy({ + contract: compiledSwapOrderUtilsSierra, + casm: compiledSwapOrderUtilsCasm, + }) + + console.log("Deploying OrderUtils") + const compiledOrderUtilsCasm = json.parse(fs.readFileSync( "./target/dev/satoru_OrderUtils.compiled_contract_class.json").toString( "ascii")) + const compiledOrderUtilsSierra = json.parse(fs.readFileSync( "./target/dev/satoru_OrderUtils.contract_class.json").toString( "ascii")) + const orderUtilsCallData: CallData = new CallData(compiledOrderUtilsSierra.abi) + const orderUtilsConstructor: Calldata = orderUtilsCallData.compile("constructor", { + increase_order_address: deployIncreaseOrderUtilsResponse.deploy.contract_address, + decrease_order_address: deployDecreaseOrderUtilsResponse.deploy.contract_address, + swap_order_address: deploySwapOrderUtilsResponse.deploy.contract_address + }) + const deployOrderUtilsResponse = await account0.declareAndDeploy({ + contract: compiledOrderUtilsSierra, + casm: compiledOrderUtilsCasm, + constructorCalldata: orderUtilsConstructor + }) + console.log("Deploying OrderHandler...") const compiledOrderHandlerCasm = json.parse(fs.readFileSync( "./target/dev/satoru_OrderHandler.compiled_contract_class.json").toString( "ascii")) const compiledOrderHandlerSierra = json.parse(fs.readFileSync( "./target/dev/satoru_OrderHandler.contract_class.json").toString( "ascii")) @@ -145,7 +190,8 @@ async function deploy() { order_vault_address: deployOrderVaultResponse.deploy.contract_address, oracle_address: deployOracleResponse.deploy.contract_address, swap_handler_address: deploySwapHandlerResponse.deploy.contract_address, - referral_storage_address: deployReferralStorageResponse.deploy.contract_address + referral_storage_address: deployReferralStorageResponse.deploy.contract_address, + order_utils_address: deployOrderUtilsResponse.deploy.contract_address }) const deployOrderHandlerResponse = await account0.declareAndDeploy({ contract: compiledOrderHandlerSierra, diff --git a/scripts/app/testDeploy.ts b/scripts/app/testDeploy.ts new file mode 100644 index 00000000..4d198b11 --- /dev/null +++ b/scripts/app/testDeploy.ts @@ -0,0 +1,88 @@ +import { Account, hash, Contract, json, Calldata, CallData, RpcProvider, shortString, ec } from "starknet" +import fs from 'fs' +import dotenv from 'dotenv' + +dotenv.config() + +async function deploy() { + // connect provider + const providerUrl = process.env.PROVIDER_URL + const provider = new RpcProvider({ nodeUrl: providerUrl! }) + // connect your account. To adapt to your own account : + const privateKey0: string = process.env.ACCOUNT_PRIVATE as string + const account0Address: string = process.env.ACCOUNT_PUBLIC as string + const account0 = new Account(provider, account0Address!, privateKey0!) + console.log("Deploying with Account: " + account0Address) + console.log("RPC: " + providerUrl) + + console.log("Deploying IncreaseOrderUtils") + const compiledIncreaseOrderUtilsCasm = json.parse(fs.readFileSync( "./target/dev/satoru_IncreaseOrderUtils.compiled_contract_class.json").toString( "ascii")) + const compiledIncreaseOrderUtilsSierra = json.parse(fs.readFileSync( "./target/dev/satoru_IncreaseOrderUtils.contract_class.json").toString( "ascii")) + const increaseOrderUtilsCallData: CallData = new CallData(compiledIncreaseOrderUtilsSierra.abi) + const increaseOrderUtilsConstructor: Calldata = increaseOrderUtilsCallData.compile("constructor", {}) + const deployIncreaseOrderUtilsResponse = await account0.declareAndDeploy({ + contract: compiledIncreaseOrderUtilsSierra, + casm: compiledIncreaseOrderUtilsCasm, + }) + + console.log("Deploying DecreaseOrderUtils") + const compiledDecreaseOrderUtilsCasm = json.parse(fs.readFileSync( "./target/dev/satoru_DecreaseOrderUtils.compiled_contract_class.json").toString( "ascii")) + const compiledDecreaseOrderUtilsSierra = json.parse(fs.readFileSync( "./target/dev/satoru_DecreaseOrderUtils.contract_class.json").toString( "ascii")) + const decreaseOrderUtilsCallData: CallData = new CallData(compiledDecreaseOrderUtilsSierra.abi) + const decreaseOrderUtilsConstructor: Calldata = decreaseOrderUtilsCallData.compile("constructor", {}) + const deployDecreaseOrderUtilsResponse = await account0.declareAndDeploy({ + contract: compiledDecreaseOrderUtilsSierra, + casm: compiledDecreaseOrderUtilsCasm, + }) + + console.log("Deploying SwapOrderUtils") + const compiledSwapOrderUtilsCasm = json.parse(fs.readFileSync( "./target/dev/satoru_SwapOrderUtils.compiled_contract_class.json").toString( "ascii")) + const compiledSwapOrderUtilsSierra = json.parse(fs.readFileSync( "./target/dev/satoru_SwapOrderUtils.contract_class.json").toString( "ascii")) + const swapOrderUtilsCallData: CallData = new CallData(compiledSwapOrderUtilsSierra.abi) + const swapOrderUtilsConstructor: Calldata = swapOrderUtilsCallData.compile("constructor", {}) + const deploySwapOrderUtilsResponse = await account0.declareAndDeploy({ + contract: compiledSwapOrderUtilsSierra, + casm: compiledSwapOrderUtilsCasm, + }) + + console.log("Deploying OrderUtils") + const compiledOrderUtilsCasm = json.parse(fs.readFileSync( "./target/dev/satoru_OrderUtils.compiled_contract_class.json").toString( "ascii")) + const compiledOrderUtilsSierra = json.parse(fs.readFileSync( "./target/dev/satoru_OrderUtils.contract_class.json").toString( "ascii")) + const orderUtilsCallData: CallData = new CallData(compiledOrderUtilsSierra.abi) + const orderUtilsConstructor: Calldata = orderUtilsCallData.compile("constructor", { + increase_order_address: deployIncreaseOrderUtilsResponse.deploy.contract_address, + decrease_order_address: deployDecreaseOrderUtilsResponse.deploy.contract_address, + swap_order_address: deploySwapOrderUtilsResponse.deploy.contract_address + }) + const deployOrderUtilsResponse = await account0.declareAndDeploy({ + contract: compiledOrderUtilsSierra, + casm: compiledOrderUtilsCasm, + constructorCalldata: orderUtilsConstructor + }) + + + const compiledOrderHandlerCasm = json.parse(fs.readFileSync( "./target/dev/satoru_OrderHandler.compiled_contract_class.json").toString( "ascii")) + const compiledOrderHandlerSierra = json.parse(fs.readFileSync( "./target/dev/satoru_OrderHandler.contract_class.json").toString( "ascii")) + const orderHandlerCallData: CallData = new CallData(compiledOrderHandlerSierra.abi) + const orderHandlerConstructor: Calldata = orderHandlerCallData.compile("constructor", { + data_store_address: "0x64b48806902a367c8598f4f95c305e8c1a1acba5f082d294a43793113115691", + role_store_address: "0x64b48806902a367c8598f4f95c305e8c1a1acba5f082d294a43793113115691", + event_emitter_address: "0x64b48806902a367c8598f4f95c305e8c1a1acba5f082d294a43793113115691", + order_vault_address: "0x64b48806902a367c8598f4f95c305e8c1a1acba5f082d294a43793113115691", + oracle_address: "0x64b48806902a367c8598f4f95c305e8c1a1acba5f082d294a43793113115691", + swap_handler_address: "0x64b48806902a367c8598f4f95c305e8c1a1acba5f082d294a43793113115691", + referral_storage_address: "0x64b48806902a367c8598f4f95c305e8c1a1acba5f082d294a43793113115691", + order_utils_address: "0x64b48806902a367c8598f4f95c305e8c1a1acba5f082d294a43793113115691" + }) + const deployOrderHandlerResponse = await account0.declareAndDeploy( + { + contract: compiledOrderHandlerSierra, + casm: compiledOrderHandlerCasm , + constructorCalldata: orderHandlerConstructor, + }, + //{ maxFee: 1485894175412100 } + ) + console.log("OrderHandler Deployed at: " + deployOrderHandlerResponse.deploy.contract_address) +} + +deploy() \ No newline at end of file diff --git a/src/exchange/adl_handler.cairo b/src/exchange/adl_handler.cairo index 038bd632..a8589f1a 100644 --- a/src/exchange/adl_handler.cairo +++ b/src/exchange/adl_handler.cairo @@ -77,6 +77,7 @@ mod AdlHandler { use satoru::exchange::base_order_handler::BaseOrderHandler::{ data_store::InternalContractMemberStateTrait as DataStoreStateTrait, event_emitter::InternalContractMemberStateTrait as EventEmitterStateTrait, + order_utils::InternalContractMemberStateTrait as OrderUtilsTrait, oracle::InternalContractMemberStateTrait as OracleStateTrait, InternalTrait as BaseOrderHandleInternalTrait, }; @@ -91,7 +92,8 @@ mod AdlHandler { use satoru::order::{ order::{SecondaryOrderType, OrderType, Order}, order_vault::{IOrderVaultDispatcher, IOrderVaultDispatcherTrait}, - base_order_utils::{ExecuteOrderParams, ExecuteOrderParamsContracts}, order_utils + base_order_utils::{ExecuteOrderParams, ExecuteOrderParamsContracts}, + order_utils::{IOrderUtilsDispatcher} }; use satoru::role::role_store::{IRoleStoreDispatcher, IRoleStoreDispatcherTrait}; use satoru::swap::swap_handler::{ISwapHandlerDispatcher, ISwapHandlerDispatcherTrait}; @@ -151,7 +153,7 @@ mod AdlHandler { oracle_address: ContractAddress, swap_handler_address: ContractAddress, referral_storage_address: ContractAddress, - order_handler_address: ContractAddress + order_utils_address: ContractAddress ) { let mut state: BaseOrderHandler::ContractState = BaseOrderHandler::unsafe_new_contract_state(); @@ -163,8 +165,10 @@ mod AdlHandler { order_vault_address, oracle_address, swap_handler_address, - referral_storage_address + referral_storage_address, + order_utils_address ); + self.order_utils.write(IOrderUtilsDispatcher { contract_address: order_utils_address }); } // ************************************************************************* @@ -282,7 +286,7 @@ mod AdlHandler { ) ); - order_utils::execute_order_utils(params); + base_order_handler_state.order_utils.read().execute_order_utils(params); // validate that the ratio of pending pnl to pool value was decreased cache diff --git a/src/exchange/base_order_handler.cairo b/src/exchange/base_order_handler.cairo index 13952562..df738a14 100644 --- a/src/exchange/base_order_handler.cairo +++ b/src/exchange/base_order_handler.cairo @@ -33,7 +33,8 @@ trait IBaseOrderHandler { order_vault_address: ContractAddress, oracle_address: ContractAddress, swap_handler_address: ContractAddress, - referral_storage_address: ContractAddress + referral_storage_address: ContractAddress, + order_utils_address: ContractAddress ); } @@ -69,6 +70,7 @@ mod BaseOrderHandler { error::OrderError, order::{SecondaryOrderType, OrderType, Order, DecreasePositionSwapType}, order_vault::{IOrderVaultDispatcher, IOrderVaultDispatcherTrait}, base_order_utils::{ExecuteOrderParams, ExecuteOrderParamsContracts}, + order_utils::{IOrderUtilsDispatcher, IOrderUtilsDispatcherTrait} }; use satoru::swap::swap_handler::{ISwapHandlerDispatcher, ISwapHandlerDispatcherTrait}; use satoru::exchange::error::ExchangeError; @@ -96,7 +98,9 @@ mod BaseOrderHandler { /// Interface to interact with the `Oracle` contract. oracle: IOracleDispatcher, /// Interface to interact with the `ReferralStorage` contract. - referral_storage: IReferralStorageDispatcher + referral_storage: IReferralStorageDispatcher, + /// Interface to interact with the `OrderUtils` contract. + order_utils: IOrderUtilsDispatcher } // ************************************************************************* @@ -121,7 +125,8 @@ mod BaseOrderHandler { order_vault_address: ContractAddress, oracle_address: ContractAddress, swap_handler_address: ContractAddress, - referral_storage_address: ContractAddress + referral_storage_address: ContractAddress, + order_utils_address: ContractAddress ) { self .initialize( @@ -131,7 +136,8 @@ mod BaseOrderHandler { order_vault_address, oracle_address, swap_handler_address, - referral_storage_address + referral_storage_address, + order_utils_address ); } @@ -149,7 +155,8 @@ mod BaseOrderHandler { order_vault_address: ContractAddress, oracle_address: ContractAddress, swap_handler_address: ContractAddress, - referral_storage_address: ContractAddress + referral_storage_address: ContractAddress, + order_utils_address: ContractAddress ) { // Make sure the contract is not already initialized. assert( @@ -170,6 +177,7 @@ mod BaseOrderHandler { self .referral_storage .write(IReferralStorageDispatcher { contract_address: referral_storage_address }); + self.order_utils.write(IOrderUtilsDispatcher { contract_address: order_utils_address }); } } diff --git a/src/exchange/liquidation_handler.cairo b/src/exchange/liquidation_handler.cairo index e29e2348..063c384d 100644 --- a/src/exchange/liquidation_handler.cairo +++ b/src/exchange/liquidation_handler.cairo @@ -59,7 +59,7 @@ mod LiquidationHandler { oracle_utils::SetPricesParams }; use satoru::order::{ - order_utils, order::{SecondaryOrderType, OrderType, Order}, + order_utils::{IOrderUtilsDispatcher}, order::{SecondaryOrderType, OrderType, Order}, order_vault::{IOrderVaultDispatcher, IOrderVaultDispatcherTrait}, base_order_utils::{ExecuteOrderParams, ExecuteOrderParamsContracts} }; @@ -77,6 +77,7 @@ mod LiquidationHandler { use satoru::exchange::base_order_handler::BaseOrderHandler::{ event_emitter::InternalContractMemberStateTrait, data_store::InternalContractMemberStateImpl, + order_utils::InternalContractMemberStateTrait as OrderUtilsTrait, oracle::InternalContractMemberStateTrait as OracleStateTrait, }; @@ -107,7 +108,8 @@ mod LiquidationHandler { order_vault_address: ContractAddress, oracle_address: ContractAddress, swap_handler_address: ContractAddress, - referral_storage_address: ContractAddress + referral_storage_address: ContractAddress, + order_utils_address: ContractAddress ) { let mut state: BaseOrderHandler::ContractState = BaseOrderHandler::unsafe_new_contract_state(); @@ -119,9 +121,9 @@ mod LiquidationHandler { order_vault_address, oracle_address, swap_handler_address, - referral_storage_address + referral_storage_address, + order_utils_address ); - let mut state: RoleModule::ContractState = RoleModule::unsafe_new_contract_state(); IRoleModule::initialize(ref state, role_store_address,); } @@ -181,7 +183,7 @@ mod LiquidationHandler { params.contracts.data_store, execute_order_feature_disabled_key(get_contract_address(), params.order.order_type) ); - order_utils::execute_order_utils(params); + state_base.execute_order_utils(params); // with_oracle_prices_after(state_base.oracle.read()); global_reentrancy_guard::non_reentrant_after(state_base.data_store.read()); diff --git a/src/exchange/order_handler.cairo b/src/exchange/order_handler.cairo index 93448834..d0ec812c 100644 --- a/src/exchange/order_handler.cairo +++ b/src/exchange/order_handler.cairo @@ -100,6 +100,7 @@ mod OrderHandler { // ************************************************************************* // Core lib imports. + use satoru::order::order_utils::IOrderUtilsDispatcherTrait; use core::starknet::SyscallResultTrait; use core::traits::Into; use starknet::ContractAddress; @@ -115,7 +116,7 @@ mod OrderHandler { use satoru::oracle::oracle_utils::{SetPricesParams, SimulatePricesParams}; use satoru::order::{ - base_order_utils::CreateOrderParams, order_utils::{create_order_utils, execute_order_utils}, //base_order_utils, + base_order_utils::CreateOrderParams, order_utils::{IOrderUtilsDispatcher}, order::{Order, OrderTrait, OrderType, SecondaryOrderType}, order_vault::{IOrderVaultDispatcher, IOrderVaultDispatcherTrait} }; @@ -132,6 +133,7 @@ mod OrderHandler { order_vault::InternalContractMemberStateTrait as OrderVaultStateTrait, referral_storage::InternalContractMemberStateTrait as ReferralStorageStateTrait, oracle::InternalContractMemberStateTrait as OracleStateTrait, + order_utils::InternalContractMemberStateTrait as OrderUtilsTrait, InternalTrait as BaseOrderHandleInternalTrait, }; use satoru::feature::feature_utils::{validate_feature}; @@ -175,7 +177,8 @@ mod OrderHandler { order_vault_address: ContractAddress, oracle_address: ContractAddress, swap_handler_address: ContractAddress, - referral_storage_address: ContractAddress + referral_storage_address: ContractAddress, + order_utils_address: ContractAddress ) { let mut state: BaseOrderHandler::ContractState = BaseOrderHandler::unsafe_new_contract_state(); @@ -187,7 +190,8 @@ mod OrderHandler { order_vault_address, oracle_address, swap_handler_address, - referral_storage_address + referral_storage_address, + order_utils_address ); } @@ -200,8 +204,6 @@ mod OrderHandler { fn create_order( ref self: ContractState, account: ContractAddress, params: CreateOrderParams ) -> felt252 { - '3. Create order'.print(); - let balance_ETH_start = IERC20Dispatcher { contract_address: contract_address_const::<'ETH'>() } @@ -212,11 +214,6 @@ mod OrderHandler { } .balance_of(contract_address_const::<'caller'>()); - '3. eth start 0 create order'.print(); - balance_ETH_start.print(); - - '3. usdc start 0 create order'.print(); - balance_USDC_start.print(); // Check only controller. let role_module_state = RoleModule::unsafe_new_contract_state(); role_module_state.only_controller(); @@ -231,28 +228,29 @@ mod OrderHandler { data_store, create_order_feature_disabled_key(get_contract_address(), params.order_type) ); - let key = create_order_utils( - data_store, - base_order_handler_state.event_emitter.read(), - base_order_handler_state.order_vault.read(), - base_order_handler_state.referral_storage.read(), - account, - params - ); + let key = base_order_handler_state + .order_utils + .read() + .create_order_utils( + data_store, + base_order_handler_state.event_emitter.read(), + base_order_handler_state.order_vault.read(), + base_order_handler_state.referral_storage.read(), + account, + params + ); non_reentrant_after(data_store); key } - + fn execute_order(ref self: ContractState, key: felt252, oracle_params: SetPricesParams) { // Check only order keeper. - '4. Execute order'.print(); let role_module_state = RoleModule::unsafe_new_contract_state(); role_module_state.only_order_keeper(); // Fetch data store. - 'firsttter'.print(); let base_order_handler_state = BaseOrderHandler::unsafe_new_contract_state(); let data_store = base_order_handler_state.data_store.read(); non_reentrant_before(data_store); @@ -262,10 +260,8 @@ mod OrderHandler { // base_order_handler_state.event_emitter.read(), // @oracle_params // ); - 'in handlerr'.print(); // TODO: Did not implement starting gas and try / catch logic as not available in Cairo self._execute_order(key, oracle_params, get_contract_address()); - 'finish execution'.print(); // oracle_modules::with_oracle_prices_after(base_order_handler_state.oracle.read()); non_reentrant_after(data_store); } @@ -338,15 +334,12 @@ mod OrderHandler { // Validate feature. validate_feature( params.contracts.data_store, - execute_order_feature_disabled_key( - get_contract_address(), params.order.order_type - ) + execute_order_feature_disabled_key(get_contract_address(), params.order.order_type) ); - execute_order_utils(params); + base_order_handler_state.order_utils.read().execute_order_utils(params); } - /// Validate that the keeper is a frozen order keeper. /// # Arguments diff --git a/src/lib.cairo b/src/lib.cairo index 2921696c..23f43a48 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -65,12 +65,12 @@ mod deposit { // `exchange` contains main satoru handlers to create and execute actions. mod exchange { - mod adl_handler; + // mod adl_handler; mod base_order_handler; mod deposit_handler; mod error; mod exchange_utils; - mod liquidation_handler; + // mod liquidation_handler; mod order_handler; mod withdrawal_handler; } diff --git a/src/order/decrease_order_utils.cairo b/src/order/decrease_order_utils.cairo index 43f6bdee..e8730c18 100644 --- a/src/order/decrease_order_utils.cairo +++ b/src/order/decrease_order_utils.cairo @@ -1,3 +1,7 @@ +// ************************************************************************* +// IMPORTS +// ************************************************************************* + // Core lib imports. use starknet::{ContractAddress, contract_address_const}; @@ -20,8 +24,8 @@ use satoru::position::position::Position; use satoru::swap::swap_utils::{SwapParams}; use satoru::position::position_utils::UpdatePositionParams; use satoru::event::event_utils::{ - LogData, LogDataTrait, Felt252IntoContractAddress, ContractAddressDictValue, I256252DictValue, - U256252DictValue, U256IntoFelt252 + Felt252IntoContractAddress, ContractAddressDictValue, I256252DictValue, U256252DictValue, + U256IntoFelt252 }; use satoru::utils::serializable_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; use satoru::market::market_token::{IMarketTokenDispatcher, IMarketTokenDispatcherTrait}; @@ -29,228 +33,340 @@ use satoru::utils::span32::{Span32, Array32Trait}; use satoru::swap::swap_handler::{ISwapHandlerDispatcher, ISwapHandlerDispatcherTrait}; use debug::PrintTrait; -// This function should return an EventLogData cause the callback_utils -// needs it. We need to find a solution for that case. -fn process_order( - params: ExecuteOrderParams -) -> LogData { //TODO check with refactor with callback_utils - let order: Order = params.order; +// ************************************************************************* +// Interface of the `OrderUtils` contract. +// ************************************************************************* +#[starknet::interface] +trait IDecreaseOrderUtils { + // This function should return an EventLogData cause the callback_utils + // needs it. We need to find a solution for that case. + fn process_order(ref self: TContractState, params: ExecuteOrderParams); - market_utils::validate_position_market_check(params.contracts.data_store, params.market); + /// Validate the oracle block numbers used for the prices in the oracle. + /// # Arguments + /// * `min_oracle_block_numbers` - The min oracle block numbers. + /// * `max_oracle_block_numbers` - The max oracle block numbers. + /// * `order_type` - The order type. + /// * `order_updated_at_block` - The block at which the order was last updated. + /// * `position_increased_at_block` - The block at which the position was last increased. + /// * `position_decrease_at_block` - The block at which the position was last decreased. + fn validate_oracle_block_numbers( + ref self: TContractState, + min_oracle_block_numbers: Span, + max_oracle_block_numbers: Span, + order_type: OrderType, + order_updated_at_block: u64, + position_increased_at_block: u64, + position_decreased_at_block: u64 + ); - let position_key: felt252 = position_utils::get_position_key( - order.account, order.market, order.initial_collateral_token, order.is_long + fn validate_output_amount( + ref self: TContractState, + oracle: IOracleDispatcher, + output_token: ContractAddress, + output_amount: u256, + min_output_amount: u256 ); - let data_store: IDataStoreDispatcher = params.contracts.data_store; - let position = data_store.get_position(position_key); - 'pass here'.print(); - position_utils::validate_non_empty_position(position); - - // validate_oracle_block_numbers( - // params.min_oracle_block_numbers.span(), - // params.max_oracle_block_numbers.span(), - // order.order_type, - // order.updated_at_block, - // position.increased_at_block, - // position.decreased_at_block - // ); - 'passed validate empty'.print(); - let mut update_position_params: UpdatePositionParams = UpdatePositionParams { - contracts: params.contracts, - market: params.market, - order: order, - order_key: params.key, - position: position, - position_key, - secondary_order_type: params.secondary_order_type - }; - 'updated params'.print(); - let mut result: DecreasePositionResult = decrease_position_utils::decrease_position( - update_position_params + // Note: that min_output_amount is treated as a USD value for this validation + fn validate_output_amount_secondary( + ref self: TContractState, + oracle: IOracleDispatcher, + output_token: ContractAddress, + output_amount: u256, + secondary_output_token: ContractAddress, + secondary_output_amount: u256, + min_output_amount: u256 ); - 'updated position'.print(); - // if the pnl_token and the collateral_token are different - // and if a swap fails or no swap was requested - // then it is possible to receive two separate tokens from decreasing - // the position - // transfer the two tokens to the user in this case and skip processing - // the swap_path - if (result.secondary_output_amount > 0) { - validate_output_amount_secondary( - params.contracts.oracle, - result.output_token, - result.output_amount, - result.secondary_output_token, - result.secondary_output_amount, - order.min_output_amount - ); - 'goes inside'.print(); - IMarketTokenDispatcher { contract_address: order.market } - .transfer_out(result.output_token, order.receiver, result.output_amount); - - IMarketTokenDispatcher { contract_address: order.market } - .transfer_out( - result.secondary_output_token, order.receiver, result.secondary_output_amount - ); - return get_output_event_data( - result.output_token, - result.output_amount, - result.secondary_output_token, - result.secondary_output_amount - ); - } + fn handle_swap_error( + ref self: TContractState, + oracle: IOracleDispatcher, + order: Order, + result: DecreasePositionResult, + reason: felt252, + reason_bytes: Span, + event_emitter: IEventEmitterDispatcher + ); +} + +#[starknet::contract] +mod DecreaseOrderUtils { + // Core lib imports. + use starknet::{ContractAddress, contract_address_const}; - let swap_param: SwapParams = SwapParams { - data_store: params.contracts.data_store, - event_emitter: params.contracts.event_emitter, - oracle: params.contracts.oracle, - bank: IBankDispatcher { contract_address: order.market }, - key: params.key, - token_in: result.output_token, - amount_in: result.output_amount, - swap_path_markets: params.swap_path_markets.span(), - min_output_amount: 0, - receiver: order.receiver, - ui_fee_receiver: order.ui_fee_receiver, + // Local imports. + use satoru::oracle::oracle::{IOracleDispatcher, IOracleDispatcherTrait}; + use satoru::data::data_store::{IDataStoreDispatcher, IDataStoreDispatcherTrait}; + use satoru::event::event_emitter::{IEventEmitterDispatcher, IEventEmitterDispatcherTrait}; + use satoru::oracle::oracle_utils; + use satoru::position::decrease_position_utils::DecreasePositionResult; + use satoru::position::decrease_position_utils; + use satoru::order::{ + base_order_utils::ExecuteOrderParams, order::Order, order::OrderType, error::OrderError, + order }; + use satoru::bank::bank::{IBankDispatcher, IBankDispatcherTrait}; - //TODO handle the swap_error when its possible - let (token_out, swap_output_amount) = params.contracts.swap_handler.swap(swap_param); + use satoru::utils::arrays; + use satoru::market::market_utils; + use satoru::position::position_utils; + use satoru::position::position::Position; + use satoru::swap::swap_utils::{SwapParams}; + use satoru::position::position_utils::UpdatePositionParams; + use satoru::event::event_utils::{ + Felt252IntoContractAddress, ContractAddressDictValue, I256252DictValue, U256252DictValue, + U256IntoFelt252 + }; + use satoru::utils::serializable_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; + use satoru::market::market_token::{IMarketTokenDispatcher, IMarketTokenDispatcherTrait}; + use satoru::utils::span32::{Span32, Array32Trait}; + use satoru::swap::swap_handler::{ISwapHandlerDispatcher, ISwapHandlerDispatcherTrait}; + use debug::PrintTrait; - validate_output_amount( - params.contracts.oracle, token_out, swap_output_amount, order.min_output_amount - ); + #[storage] + struct Storage {} - return get_output_event_data(token_out, swap_output_amount, contract_address_const::<0>(), 0); -} + // ************************************************************************* + // EXTERNAL FUNCTIONS + // ************************************************************************* + #[abi(embed_v0)] + impl DecreaseOrderUtilsImpl of super::IDecreaseOrderUtils { + // This function should return an EventLogData cause the callback_utils + // needs it. We need to find a solution for that case. + fn process_order( + ref self: ContractState, params: ExecuteOrderParams + ) { //TODO check with refactor with callback_utils + let order: Order = params.order; + market_utils::validate_position_market_check( + params.contracts.data_store, params.market + ); -/// Validate the oracle block numbers used for the prices in the oracle. -/// # Arguments -/// * `min_oracle_block_numbers` - The min oracle block numbers. -/// * `max_oracle_block_numbers` - The max oracle block numbers. -/// * `order_type` - The order type. -/// * `order_updated_at_block` - The block at which the order was last updated. -/// * `position_increased_at_block` - The block at which the position was last increased. -/// * `position_decrease_at_block` - The block at which the position was last decreased. -fn validate_oracle_block_numbers( - min_oracle_block_numbers: Span, - max_oracle_block_numbers: Span, - order_type: OrderType, - order_updated_at_block: u64, - position_increased_at_block: u64, - position_decreased_at_block: u64 -) { - if order_type == OrderType::MarketDecrease { - oracle_utils::validate_block_number_within_range( - min_oracle_block_numbers, max_oracle_block_numbers, order_updated_at_block - ); - return; - } + let position_key: felt252 = position_utils::get_position_key( + order.account, order.market, order.initial_collateral_token, order.is_long + ); - if (order_type == OrderType::LimitDecrease || order_type == OrderType::StopLossDecrease) { - let mut latest_updated_at_block: u64 = position_increased_at_block; - if (order_updated_at_block > position_increased_at_block) { - latest_updated_at_block = order_updated_at_block - } - if (!arrays::are_gte_u64(min_oracle_block_numbers, latest_updated_at_block)) { - OrderError::ORACLE_BLOCK_NUMBERS_ARE_SMALLER_THAN_REQUIRED( - min_oracle_block_numbers, latest_updated_at_block + let data_store: IDataStoreDispatcher = params.contracts.data_store; + let position = data_store.get_position(position_key); + 'pass here'.print(); + position_utils::validate_non_empty_position(position); + + // validate_oracle_block_numbers( + // params.min_oracle_block_numbers.span(), + // params.max_oracle_block_numbers.span(), + // order.order_type, + // order.updated_at_block, + // position.increased_at_block, + // position.decreased_at_block + // ); + 'passed validate empty'.print(); + let mut update_position_params: UpdatePositionParams = UpdatePositionParams { + contracts: params.contracts, + market: params.market, + order: order, + order_key: params.key, + position: position, + position_key, + secondary_order_type: params.secondary_order_type + }; + 'updated params'.print(); + let mut result: DecreasePositionResult = decrease_position_utils::decrease_position( + update_position_params ); + 'updated position'.print(); + // if the pnl_token and the collateral_token are different + // and if a swap fails or no swap was requested + // then it is possible to receive two separate tokens from decreasing + // the position + // transfer the two tokens to the user in this case and skip processing + // the swap_path + if (result.secondary_output_amount > 0) { + self + .validate_output_amount_secondary( + params.contracts.oracle, + result.output_token, + result.output_amount, + result.secondary_output_token, + result.secondary_output_amount, + order.min_output_amount + ); + 'goes inside'.print(); + IMarketTokenDispatcher { contract_address: order.market } + .transfer_out(result.output_token, order.receiver, result.output_amount); + + IMarketTokenDispatcher { contract_address: order.market } + .transfer_out( + result.secondary_output_token, + order.receiver, + result.secondary_output_amount + ); + // return get_output_event_data( + // result.output_token, + // result.output_amount, + // result.secondary_output_token, + // result.secondary_output_amount + // ); + } + + let swap_param: SwapParams = SwapParams { + data_store: params.contracts.data_store, + event_emitter: params.contracts.event_emitter, + oracle: params.contracts.oracle, + bank: IBankDispatcher { contract_address: order.market }, + key: params.key, + token_in: result.output_token, + amount_in: result.output_amount, + swap_path_markets: params.swap_path_markets.span(), + min_output_amount: 0, + receiver: order.receiver, + ui_fee_receiver: order.ui_fee_receiver, + }; + + //TODO handle the swap_error when its possible + let (token_out, swap_output_amount) = params.contracts.swap_handler.swap(swap_param); + + self + .validate_output_amount( + params.contracts.oracle, token_out, swap_output_amount, order.min_output_amount + ); + // return get_output_event_data(token_out, swap_output_amount, contract_address_const::<0>(), 0); } - return; - } - if (order_type == OrderType::Liquidation) { - let mut latest_updated_at_block: u64 = position_decreased_at_block; - if (position_increased_at_block > position_decreased_at_block) { - latest_updated_at_block = position_increased_at_block + + + /// Validate the oracle block numbers used for the prices in the oracle. + /// # Arguments + /// * `min_oracle_block_numbers` - The min oracle block numbers. + /// * `max_oracle_block_numbers` - The max oracle block numbers. + /// * `order_type` - The order type. + /// * `order_updated_at_block` - The block at which the order was last updated. + /// * `position_increased_at_block` - The block at which the position was last increased. + /// * `position_decrease_at_block` - The block at which the position was last decreased. + fn validate_oracle_block_numbers( + ref self: ContractState, + min_oracle_block_numbers: Span, + max_oracle_block_numbers: Span, + order_type: OrderType, + order_updated_at_block: u64, + position_increased_at_block: u64, + position_decreased_at_block: u64 + ) { + if order_type == OrderType::MarketDecrease { + oracle_utils::validate_block_number_within_range( + min_oracle_block_numbers, max_oracle_block_numbers, order_updated_at_block + ); + return; + } + + if (order_type == OrderType::LimitDecrease + || order_type == OrderType::StopLossDecrease) { + let mut latest_updated_at_block: u64 = position_increased_at_block; + if (order_updated_at_block > position_increased_at_block) { + latest_updated_at_block = order_updated_at_block + } + if (!arrays::are_gte_u64(min_oracle_block_numbers, latest_updated_at_block)) { + OrderError::ORACLE_BLOCK_NUMBERS_ARE_SMALLER_THAN_REQUIRED( + min_oracle_block_numbers, latest_updated_at_block + ); + } + return; + } + if (order_type == OrderType::Liquidation) { + let mut latest_updated_at_block: u64 = position_decreased_at_block; + if (position_increased_at_block > position_decreased_at_block) { + latest_updated_at_block = position_increased_at_block + } + if (!arrays::are_gte_u64(min_oracle_block_numbers, latest_updated_at_block)) { + OrderError::ORACLE_BLOCK_NUMBERS_ARE_SMALLER_THAN_REQUIRED( + min_oracle_block_numbers, latest_updated_at_block + ); + } + return; + } + panic_with_felt252(OrderError::UNSUPPORTED_ORDER_TYPE); } - if (!arrays::are_gte_u64(min_oracle_block_numbers, latest_updated_at_block)) { - OrderError::ORACLE_BLOCK_NUMBERS_ARE_SMALLER_THAN_REQUIRED( - min_oracle_block_numbers, latest_updated_at_block - ); + + // Note: that min_output_amount is treated as a USD value for this validation + fn validate_output_amount( + ref self: ContractState, + oracle: IOracleDispatcher, + output_token: ContractAddress, + output_amount: u256, + min_output_amount: u256 + ) { + let output_token_price: u256 = oracle.get_primary_price(output_token).min; + let output_usd: u256 = output_amount * output_token_price; + + if (output_usd < min_output_amount) { + 'error here'.print(); + OrderError::INSUFFICIENT_OUTPUT_AMOUNT(output_usd, output_token_price); + 'after error'.print(); + } } - return; - } - panic_with_felt252(OrderError::UNSUPPORTED_ORDER_TYPE); -} -// Note: that min_output_amount is treated as a USD value for this validation -fn validate_output_amount( - oracle: IOracleDispatcher, - output_token: ContractAddress, - output_amount: u256, - min_output_amount: u256 -) { - let output_token_price: u256 = oracle.get_primary_price(output_token).min; - let output_usd: u256 = output_amount * output_token_price; - - if (output_usd < min_output_amount) { - 'error here'.print(); - OrderError::INSUFFICIENT_OUTPUT_AMOUNT(output_usd, output_token_price); - 'after error'.print(); - } -} + // Note: that min_output_amount is treated as a USD value for this validation + fn validate_output_amount_secondary( + ref self: ContractState, + oracle: IOracleDispatcher, + output_token: ContractAddress, + output_amount: u256, + secondary_output_token: ContractAddress, + secondary_output_amount: u256, + min_output_amount: u256 + ) { + let output_token_price: u256 = oracle.get_primary_price(output_token).min; + let output_usd: u256 = output_amount * output_token_price; -// Note: that min_output_amount is treated as a USD value for this validation -fn validate_output_amount_secondary( - oracle: IOracleDispatcher, - output_token: ContractAddress, - output_amount: u256, - secondary_output_token: ContractAddress, - secondary_output_amount: u256, - min_output_amount: u256 -) { - let output_token_price: u256 = oracle.get_primary_price(output_token).min; - let output_usd: u256 = output_amount * output_token_price; - - let secondary_output_token_price: u256 = oracle.get_primary_price(secondary_output_token).min; - let seconday_output_usd: u256 = secondary_output_amount * secondary_output_token_price; - - let total_output_usd: u256 = output_usd + seconday_output_usd; - - if (total_output_usd < min_output_amount) { - 'error here 2'.print(); - OrderError::INSUFFICIENT_OUTPUT_AMOUNT(output_usd, output_token_price); - 'after error 2'.print(); - } -} + let secondary_output_token_price: u256 = oracle + .get_primary_price(secondary_output_token) + .min; + let seconday_output_usd: u256 = secondary_output_amount * secondary_output_token_price; -fn handle_swap_error( - oracle: IOracleDispatcher, - order: Order, - result: DecreasePositionResult, - reason: felt252, - reason_bytes: Span, - event_emitter: IEventEmitterDispatcher -) { - event_emitter.emit_swap_reverted(reason, reason_bytes); - - validate_output_amount( - oracle, result.output_token, result.output_amount, order.min_output_amount - ); + let total_output_usd: u256 = output_usd + seconday_output_usd; - IMarketTokenDispatcher { contract_address: order.market } - .transfer_out(result.output_token, order.receiver, result.output_amount); -} + if (total_output_usd < min_output_amount) { + 'error here 2'.print(); + OrderError::INSUFFICIENT_OUTPUT_AMOUNT(output_usd, output_token_price); + 'after error 2'.print(); + } + } + + fn handle_swap_error( + ref self: ContractState, + oracle: IOracleDispatcher, + order: Order, + result: DecreasePositionResult, + reason: felt252, + reason_bytes: Span, + event_emitter: IEventEmitterDispatcher + ) { + event_emitter.emit_swap_reverted(reason, reason_bytes); -// This function should return an EventLogData cause the callback_utils -// needs it. We need to find a solution for that case. -fn get_output_event_data( - output_token: ContractAddress, - output_amount: u256, - secondary_output_token: ContractAddress, - secondary_output_amount: u256 -) -> LogData { - let mut log_data: LogData = Default::default(); + self + .validate_output_amount( + oracle, result.output_token, result.output_amount, order.min_output_amount + ); - log_data.address_dict.insert_single('output_token', output_token); - log_data.address_dict.insert_single('secondary_output_token', secondary_output_token); + IMarketTokenDispatcher { contract_address: order.market } + .transfer_out(result.output_token, order.receiver, result.output_amount); + } + // This function should return an EventLogData cause the callback_utils + // needs it. We need to find a solution for that case. + // fn get_output_event_data( + // output_token: ContractAddress, + // output_amount: u256, + // secondary_output_token: ContractAddress, + // secondary_output_amount: u256 + // ) { //-> LogData { + // let mut log_data: LogData = Default::default(); - log_data.uint_dict.insert_single('output_amount', output_amount); - log_data.uint_dict.insert_single('secondary_output_amount', secondary_output_amount); + // log_data.address_dict.insert_single('output_token', output_token); + // log_data.address_dict.insert_single('secondary_output_token', secondary_output_token); - log_data + // log_data.uint_dict.insert_single('output_amount', output_amount); + // log_data.uint_dict.insert_single('secondary_output_amount', secondary_output_amount); + + // //log_data + // } + } } diff --git a/src/order/increase_order_utils.cairo b/src/order/increase_order_utils.cairo index 6bb2d623..61e42161 100644 --- a/src/order/increase_order_utils.cairo +++ b/src/order/increase_order_utils.cairo @@ -1,3 +1,7 @@ +// ************************************************************************* +// IMPORTS +// ************************************************************************* + // Core lib imports. use starknet::ContractAddress; @@ -11,131 +15,189 @@ use satoru::market::market_utils; use satoru::swap::swap_utils; use satoru::bank::bank::{IBankDispatcher, IBankDispatcherTrait}; use satoru::position::{position_utils, error::PositionError, increase_position_utils}; -use satoru::event::event_utils; use debug::PrintTrait; // External imports. use alexandria_data_structures::array_ext::SpanTraitExt; -/// Process an increase order. -/// # Arguments -/// * `params` - The execute order params. -/// # Returns -/// * `EventLogData` - The event log data. -/// This function should return an EventLogData cause the callback_utils -/// needs it. We need to find a solution for that case. -fn process_order(params: ExecuteOrderParams) -> event_utils::LogData { - market_utils::validate_position_market(params.contracts.data_store, params.market.market_token); - - let (collateral_token, collateral_increment_amount) = swap_utils::swap( - @swap_utils::SwapParams { - data_store: params.contracts.data_store, - event_emitter: params.contracts.event_emitter, - oracle: params.contracts.oracle, - bank: IBankDispatcher { - contract_address: params.contracts.order_vault.contract_address - }, - key: params.key, - token_in: params.order.initial_collateral_token, - amount_in: params.order.initial_collateral_delta_amount, - swap_path_markets: params.swap_path_markets.span(), - min_output_amount: params.order.min_output_amount, - receiver: params.order.market, - ui_fee_receiver: params.order.ui_fee_receiver, - } - ); +// ************************************************************************* +// Interface of the `OrderUtils` contract. +// ************************************************************************* +#[starknet::interface] +trait IIncreaseOrderUtils { + /// Process an increase order. + /// # Arguments + /// * `params` - The execute order params. + /// # Returns + /// * `EventLogData` - The event log data. + /// This function should return an EventLogData cause the callback_utils + /// needs it. We need to find a solution for that case. + fn process_order(ref self: TContractState, params: ExecuteOrderParams); - 'swap made done'.print(); - market_utils::validate_market_collateral_token(params.market, collateral_token); - 'AFTER VALIDATE'.print(); - let position_key = position_utils::get_position_key( - params.order.account, params.order.market, collateral_token, params.order.is_long, - ); - params.order.account.print(); - params.order.market.print(); - collateral_token.print(); - params.order.is_long.print(); - - 'AFTER VALIDATE1'.print(); - let mut position = params.contracts.data_store.get_position(position_key); - 'AFTER VALIDATE2'.print(); - // Initialize position - if position.account.is_zero() { - position.account = params.order.account; - if !position.market.is_zero() || !position.collateral_token.is_zero() { - panic_with_felt252(PositionError::UNEXPECTED_POSITION_STATE); - } - 'AFTER VALIDATE3'.print(); - position.market = params.order.market; - position.collateral_token = collateral_token; - position.is_long = params.order.is_long; - }; - 'AFTER VALIDATE4'.print(); - // validate_oracle_block_numbers( - // params.min_oracle_block_numbers.span(), - // params.max_oracle_block_numbers.span(), - // params.order.order_type, - // params.order.updated_at_block - // ); - 'AFTER VALIDATE5'.print(); - increase_position_utils::increase_position( - position_utils::UpdatePositionParams { - contracts: params.contracts, - market: params.market, - order: params.order, - order_key: params.key, - position: position, - position_key: position_key, - secondary_order_type: params.secondary_order_type, - }, - collateral_increment_amount + /// Validate the oracle block numbers used for the prices in the oracle. + /// # Arguments + /// * `min_oracle_block_numbers` - The min oracle block numbers. + /// * `max_oracle_block_numbers` - The max oracle block numbers. + /// * `order_type` - The order type. + /// * `order_updated_at_block` - The block at which the order was last updated. + fn validate_oracle_block_numbers( + ref self: TContractState, + min_oracle_block_numbers: Span, + max_oracle_block_numbers: Span, + order_type: OrderType, + order_updated_at_block: u64 ); - 'AFTER VALIDATE6'.print(); - let position_updated = params.contracts.data_store.get_position(position_key); - position_updated.size_in_usd.print(); - 'AFTER POSIOTOPN UPDATED'.print(); - - let log: event_utils::LogData = Default::default(); - log } -/// Validate the oracle block numbers used for the prices in the oracle. -/// # Arguments -/// * `min_oracle_block_numbers` - The min oracle block numbers. -/// * `max_oracle_block_numbers` - The max oracle block numbers. -/// * `order_type` - The order type. -/// * `order_updated_at_block` - The block at which the order was last updated. -fn validate_oracle_block_numbers( - min_oracle_block_numbers: Span, - max_oracle_block_numbers: Span, - order_type: OrderType, - order_updated_at_block: u64 -) { - if order_type == OrderType::MarketIncrease { - oracle_utils::validate_block_number_within_range( - min_oracle_block_numbers, max_oracle_block_numbers, order_updated_at_block - ); - return; +#[starknet::contract] +mod IncreaseOrderUtils { + // Core lib imports. + use starknet::ContractAddress; + + // Local imports. + use satoru::order::{ + base_order_utils::ExecuteOrderParams, order::{Order, OrderType}, error::OrderError }; + use satoru::data::{data_store::IDataStoreDispatcherTrait, error::DataError}; + use satoru::oracle::{oracle_utils, error::OracleError}; + use satoru::market::market_utils; + use satoru::swap::swap_utils; + use satoru::bank::bank::{IBankDispatcher, IBankDispatcherTrait}; + use satoru::position::{position_utils, error::PositionError, increase_position_utils}; + use debug::PrintTrait; + + // External imports. + use alexandria_data_structures::array_ext::SpanTraitExt; - if order_type == OrderType::LimitIncrease { - // since the oracle blocks are only validated against the orderUpdatedAtBlock - // it is possible to cause a limit increase order to become executable by - // having the order have an initial collateral amount of zero then opening - // a position and depositing collateral if the limit order is desired to be executed - // for this case, when the limit order price is reached, the order should be frozen - // the frozen order keepers should only execute frozen orders if the latest prices - // fulfill the limit price - let min_oracle_block_number = min_oracle_block_numbers - .min() - .expect(OracleError::EMPTY_ORACLE_BLOCK_NUMBERS); - if min_oracle_block_number < order_updated_at_block { - OracleError::ORACLE_BLOCK_NUMBERS_ARE_SMALLER_THAN_REQUIRED( - min_oracle_block_numbers, order_updated_at_block + #[storage] + struct Storage {} + + // ************************************************************************* + // EXTERNAL FUNCTIONS + // ************************************************************************* + #[abi(embed_v0)] + impl IncreaseOrderUtilsImpl of super::IIncreaseOrderUtils { + /// Process an increase order. + /// # Arguments + /// * `params` - The execute order params. + /// # Returns + /// * `EventLogData` - The event log data. + /// This function should return an EventLogData cause the callback_utils + /// needs it. We need to find a solution for that case. + fn process_order(ref self: ContractState, params: ExecuteOrderParams) { + market_utils::validate_position_market( + params.contracts.data_store, params.market.market_token ); + + let (collateral_token, collateral_increment_amount) = swap_utils::swap( + @swap_utils::SwapParams { + data_store: params.contracts.data_store, + event_emitter: params.contracts.event_emitter, + oracle: params.contracts.oracle, + bank: IBankDispatcher { + contract_address: params.contracts.order_vault.contract_address + }, + key: params.key, + token_in: params.order.initial_collateral_token, + amount_in: params.order.initial_collateral_delta_amount, + swap_path_markets: params.swap_path_markets.span(), + min_output_amount: params.order.min_output_amount, + receiver: params.order.market, + ui_fee_receiver: params.order.ui_fee_receiver, + } + ); + + 'swap made done'.print(); + market_utils::validate_market_collateral_token(params.market, collateral_token); + 'AFTER VALIDATE'.print(); + let position_key = position_utils::get_position_key( + params.order.account, params.order.market, collateral_token, params.order.is_long, + ); + params.order.account.print(); + params.order.market.print(); + collateral_token.print(); + params.order.is_long.print(); + + 'AFTER VALIDATE1'.print(); + let mut position = params.contracts.data_store.get_position(position_key); + 'AFTER VALIDATE2'.print(); + // Initialize position + if position.account.is_zero() { + position.account = params.order.account; + if !position.market.is_zero() || !position.collateral_token.is_zero() { + panic_with_felt252(PositionError::UNEXPECTED_POSITION_STATE); + } + 'AFTER VALIDATE3'.print(); + position.market = params.order.market; + position.collateral_token = collateral_token; + position.is_long = params.order.is_long; + }; + 'AFTER VALIDATE4'.print(); + // validate_oracle_block_numbers( + // params.min_oracle_block_numbers.span(), + // params.max_oracle_block_numbers.span(), + // params.order.order_type, + // params.order.updated_at_block + // ); + 'AFTER VALIDATE5'.print(); + increase_position_utils::increase_position( + position_utils::UpdatePositionParams { + contracts: params.contracts, + market: params.market, + order: params.order, + order_key: params.key, + position: position, + position_key: position_key, + secondary_order_type: params.secondary_order_type, + }, + collateral_increment_amount + ); + 'AFTER VALIDATE6'.print(); + let position_updated = params.contracts.data_store.get_position(position_key); + position_updated.size_in_usd.print(); + 'AFTER POSIOTOPN UPDATED'.print(); } - return; - } - panic(array![OrderError::UNSUPPORTED_ORDER_TYPE]); + /// Validate the oracle block numbers used for the prices in the oracle. + /// # Arguments + /// * `min_oracle_block_numbers` - The min oracle block numbers. + /// * `max_oracle_block_numbers` - The max oracle block numbers. + /// * `order_type` - The order type. + /// * `order_updated_at_block` - The block at which the order was last updated. + fn validate_oracle_block_numbers( + ref self: ContractState, + min_oracle_block_numbers: Span, + max_oracle_block_numbers: Span, + order_type: OrderType, + order_updated_at_block: u64 + ) { + if order_type == OrderType::MarketIncrease { + oracle_utils::validate_block_number_within_range( + min_oracle_block_numbers, max_oracle_block_numbers, order_updated_at_block + ); + return; + }; + + if order_type == OrderType::LimitIncrease { + // since the oracle blocks are only validated against the orderUpdatedAtBlock + // it is possible to cause a limit increase order to become executable by + // having the order have an initial collateral amount of zero then opening + // a position and depositing collateral if the limit order is desired to be executed + // for this case, when the limit order price is reached, the order should be frozen + // the frozen order keepers should only execute frozen orders if the latest prices + // fulfill the limit price + let min_oracle_block_number = min_oracle_block_numbers + .min() + .expect(OracleError::EMPTY_ORACLE_BLOCK_NUMBERS); + if min_oracle_block_number < order_updated_at_block { + OracleError::ORACLE_BLOCK_NUMBERS_ARE_SMALLER_THAN_REQUIRED( + min_oracle_block_numbers, order_updated_at_block + ); + } + return; + } + + panic(array![OrderError::UNSUPPORTED_ORDER_TYPE]); + } + } } diff --git a/src/order/order_utils.cairo b/src/order/order_utils.cairo index b083335c..90ddbc85 100644 --- a/src/order/order_utils.cairo +++ b/src/order/order_utils.cairo @@ -3,373 +3,527 @@ // ************************************************************************* // Core lib imports. -use starknet::{ContractAddress, contract_address_const}; -use clone::Clone; -use debug::PrintTrait; +use starknet::ContractAddress; // Local imports. -use satoru::order::base_order_utils::{ExecuteOrderParams, CreateOrderParams}; -use satoru::order::base_order_utils; +use satoru::oracle::oracle_utils::{SetPricesParams, SimulatePricesParams}; +use satoru::order::{base_order_utils::{CreateOrderParams, ExecuteOrderParams}, order::Order}; +use satoru::order::order_vault::{IOrderVaultDispatcher, IOrderVaultDispatcherTrait}; use satoru::data::data_store::{IDataStoreDispatcher, IDataStoreDispatcherTrait}; use satoru::event::event_emitter::{IEventEmitterDispatcher, IEventEmitterDispatcherTrait}; -use satoru::order::order_vault::{IOrderVaultDispatcher, IOrderVaultDispatcherTrait}; use satoru::mock::referral_storage::{IReferralStorageDispatcher, IReferralStorageDispatcherTrait}; -use satoru::market::market_utils; -use satoru::nonce::nonce_utils; -use satoru::utils::account_utils; -use satoru::referral::referral_utils; -use satoru::token::token_utils; -use satoru::callback::callback_utils; -use satoru::gas::gas_utils; -use satoru::order::order::{Order, OrderType, OrderTrait}; use satoru::event::event_utils::{ - LogData, LogDataTrait, Felt252IntoContractAddress, ContractAddressDictValue, I256252DictValue + Felt252IntoContractAddress, ContractAddressDictValue, I256252DictValue }; -use satoru::utils::serializable_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; -use satoru::order::error::OrderError; -use satoru::order::{increase_order_utils, decrease_order_utils, swap_order_utils}; -use satoru::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; - -/// Creates an order in the order store. -/// # Arguments -/// * `data_store` - The `DataStore` contract dispatcher. -/// * `event_emitter` - The `EventEmitter` contract dispatcher. -/// * `order_vault` - The `OrderVault` contract dispatcher. -/// * `referral_store` - The referral storage instance to use. -/// * `account` - The order account. -/// * `params` - The parameters used to create the order. -/// # Returns -/// Return the key of the created order. -fn create_order_utils( //TODO and fix when fee_token is implememted - data_store: IDataStoreDispatcher, - event_emitter: IEventEmitterDispatcher, - order_vault: IOrderVaultDispatcher, - referral_storage: IReferralStorageDispatcher, - account: ContractAddress, - mut params: CreateOrderParams -) -> felt252 { - '4. Create Order in order store'.print(); - - let balance_ETH_start = IERC20Dispatcher { contract_address: contract_address_const::<'ETH'>() } - .balance_of(contract_address_const::<'caller'>()); - - let balance_USDC_start = IERC20Dispatcher { - contract_address: contract_address_const::<'USDC'>() - } - .balance_of(contract_address_const::<'caller'>()); - - '4. eth start create order'.print(); - balance_ETH_start.print(); - - '4. usdc start create order'.print(); - balance_USDC_start.print(); +// ************************************************************************* +// Interface of the `OrderUtils` contract. +// ************************************************************************* +#[starknet::interface] +trait IOrderUtils { + /// Creates an order in the order store. + /// # Arguments + /// * `data_store` - The `DataStore` contract dispatcher. + /// * `event_emitter` - The `EventEmitter` contract dispatcher. + /// * `order_vault` - The `OrderVault` contract dispatcher. + /// * `referral_store` - The referral storage instance to use. + /// * `account` - The order account. + /// * `params` - The parameters used to create the order. + /// # Returns + /// Return the key of the created order. + fn create_order_utils( + ref self: TContractState, + data_store: IDataStoreDispatcher, + event_emitter: IEventEmitterDispatcher, + order_vault: IOrderVaultDispatcher, + referral_storage: IReferralStorageDispatcher, + account: ContractAddress, + params: CreateOrderParams + ) -> felt252; + + fn execute_order_utils(ref self: TContractState, params: ExecuteOrderParams); + + /// Process an order execution. + /// # Arguments + /// * `params` - The parameters used to process the order. + fn process_order( + ref self: TContractState, params: ExecuteOrderParams + ); //TODO add LogData return value + + /// Cancels an order. + /// # Arguments + /// * `data_store` - The `DataStore` contract dispatcher. + /// * `event_emitter` - The `EventEmitter` contract dispatcher. + /// * `order_vault` - The `OrderVault` contract dispatcher. + /// * `key` - The key of the order to cancel + /// * `keeper` - The keeper sending the transaction. + /// * `starting_gas` - The starting gas of the transaction. + /// * `reason` - The reason for cancellation. + /// # Returns + /// Return the key of the created order. + fn cancel_order( + ref self: TContractState, + data_store: IDataStoreDispatcher, + event_emitter: IEventEmitterDispatcher, + order_vault: IOrderVaultDispatcher, + key: felt252, + keeper: ContractAddress, + starting_gas: u256, + reason: felt252, + reason_bytes: Array + ); - account_utils::validate_account(account); - referral_utils::set_trader_referral_code(referral_storage, account, params.referral_code); + /// Freezes an order. + /// # Arguments + /// * `data_store` - The `DataStore` contract dispatcher. + /// * `event_emitter` - The `EventEmitter` contract dispatcher. + /// * `order_vault` - The `OrderVault` contract dispatcher. + /// * `key` - The key of the order to freeze + /// * `keeper` - The keeper sending the transaction. + /// * `starting_gas` - The starting gas of the transaction. + /// * `reason` - The reason the order was frozen. + /// # Returns + /// Return the key of the created order. + fn freeze_order( + ref self: TContractState, + data_store: IDataStoreDispatcher, + event_emitter: IEventEmitterDispatcher, + order_vault: IOrderVaultDispatcher, + key: felt252, + keeper: ContractAddress, + starting_gas: u256, + reason: felt252, + reason_bytes: Array + ); +} - let mut initial_collateral_delta_amount = 0; - let fee_token = token_utils::fee_token(data_store); +#[starknet::contract] +mod OrderUtils { + // Core lib imports. + use starknet::{ContractAddress, contract_address_const}; + use clone::Clone; + use debug::PrintTrait; + // Local imports. + use satoru::order::base_order_utils::{ExecuteOrderParams, CreateOrderParams}; + use satoru::order::base_order_utils; + use satoru::data::data_store::{IDataStoreDispatcher, IDataStoreDispatcherTrait}; + use satoru::event::event_emitter::{IEventEmitterDispatcher, IEventEmitterDispatcherTrait}; + use satoru::order::order_vault::{IOrderVaultDispatcher, IOrderVaultDispatcherTrait}; + use satoru::mock::referral_storage::{ + IReferralStorageDispatcher, IReferralStorageDispatcherTrait + }; + use satoru::market::market_utils; + use satoru::nonce::nonce_utils; + use satoru::utils::account_utils; + use satoru::referral::referral_utils; + use satoru::token::token_utils; + use satoru::callback::callback_utils; + use satoru::gas::gas_utils; + use satoru::order::order::{Order, OrderType, OrderTrait}; + use satoru::event::event_utils::{ + Felt252IntoContractAddress, ContractAddressDictValue, I256252DictValue + }; + use satoru::utils::serializable_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; + use satoru::order::error::OrderError; - let mut should_record_separate_execution_fee_transfer = true; + use satoru::order::increase_order_utils::{ + IIncreaseOrderUtilsDispatcher, IIncreaseOrderUtilsDispatcherTrait + }; + use satoru::order::decrease_order_utils::{ + IDecreaseOrderUtilsDispatcher, IDecreaseOrderUtilsDispatcherTrait + }; + use satoru::order::swap_order_utils::{ + ISwapOrderUtilsDispatcher, ISwapOrderUtilsDispatcherTrait + }; - if (params.order_type == OrderType::MarketSwap - || params.order_type == OrderType::LimitSwap - || params.order_type == OrderType::MarketIncrease - || params.order_type == OrderType::LimitIncrease) { - // for swaps and increase orders, the initialCollateralDeltaAmount is set based on the amount of tokens - // transferred to the orderVault - initial_collateral_delta_amount = order_vault - .record_transfer_in(params.initial_collateral_token); - if (params.initial_collateral_token == fee_token) { - if (initial_collateral_delta_amount < params.execution_fee) { - OrderError::INSUFFICIENT_WNT_AMOUNT_FOR_EXECUTION_FEE( - initial_collateral_delta_amount, params.execution_fee - ); - } - initial_collateral_delta_amount -= params.execution_fee; - should_record_separate_execution_fee_transfer = false; - } - } else if (params.order_type == OrderType::MarketDecrease - || params.order_type == OrderType::LimitDecrease - || params.order_type == OrderType::StopLossDecrease) { - // for decrease orders, the initialCollateralDeltaAmount is based on the passed in value - initial_collateral_delta_amount = params.initial_collateral_delta_amount; - } else { - OrderError::ORDER_TYPE_CANNOT_BE_CREATED(params.order_type); - } + use satoru::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; - if (should_record_separate_execution_fee_transfer) { - let fee_token_amount = order_vault.record_transfer_in(fee_token); - if (fee_token_amount < params.execution_fee) { - OrderError::INSUFFICIENT_WNT_AMOUNT_FOR_EXECUTION_FEE( - fee_token_amount, params.execution_fee - ); - } - params.execution_fee = fee_token_amount; + #[storage] + struct Storage { + increase_order_utils: IIncreaseOrderUtilsDispatcher, + decrease_order_utils: IDecreaseOrderUtilsDispatcher, + swap_order_utils: ISwapOrderUtilsDispatcher, } - if (base_order_utils::is_position_order(params.order_type)) { - market_utils::validate_position_market(data_store, params.market); + // ************************************************************************* + // CONSTRUCTOR + // ************************************************************************* + #[constructor] + fn constructor( + ref self: ContractState, + increase_order_address: ContractAddress, + decrease_order_address: ContractAddress, + swap_order_address: ContractAddress + ) { + self + .increase_order_utils + .write(IIncreaseOrderUtilsDispatcher { contract_address: increase_order_address }); + self + .decrease_order_utils + .write(IDecreaseOrderUtilsDispatcher { contract_address: decrease_order_address }); + self + .swap_order_utils + .write(ISwapOrderUtilsDispatcher { contract_address: swap_order_address }); } - // validate swap path markets - market_utils::validate_swap_path(data_store, params.swap_path); - - let mut order = Order { - key: 0, - order_type: params.order_type, - decrease_position_swap_type: params.decrease_position_swap_type, - account, - receiver: params.receiver, - callback_contract: params.callback_contract, - ui_fee_receiver: params.ui_fee_receiver, - market: params.market, - initial_collateral_token: params.initial_collateral_token, - swap_path: params.swap_path, - size_delta_usd: params.size_delta_usd, - initial_collateral_delta_amount, - trigger_price: params.trigger_price, - acceptable_price: params.acceptable_price, - execution_fee: params.execution_fee, - callback_gas_limit: params.callback_gas_limit, - min_output_amount: params.min_output_amount, - /// The block at which the order was last updated. - updated_at_block: 0, - is_long: params.is_long, - /// Whether the order is frozen. - is_frozen: false, - }; - - account_utils::validate_receiver(order.receiver); - - callback_utils::validate_callback_gas_limit(data_store, order.callback_gas_limit); + // ************************************************************************* + // EXTERNAL FUNCTIONS + // ************************************************************************* + #[abi(embed_v0)] + impl OrderUtilsImpl of super::IOrderUtils { + /// Creates an order in the order store. + /// # Arguments + /// * `data_store` - The `DataStore` contract dispatcher. + /// * `event_emitter` - The `EventEmitter` contract dispatcher. + /// * `order_vault` - The `OrderVault` contract dispatcher. + /// * `referral_store` - The referral storage instance to use. + /// * `account` - The order account. + /// * `params` - The parameters used to create the order. + /// # Returns + /// Return the key of the created order. + fn create_order_utils( //TODO and fix when fee_token is implememted + ref self: ContractState, + data_store: IDataStoreDispatcher, + event_emitter: IEventEmitterDispatcher, + order_vault: IOrderVaultDispatcher, + referral_storage: IReferralStorageDispatcher, + account: ContractAddress, + mut params: CreateOrderParams + ) -> felt252 { + let balance_ETH_start = IERC20Dispatcher { + contract_address: contract_address_const::<'ETH'>() + } + .balance_of(contract_address_const::<'caller'>()); - let estimated_gas_limit = gas_utils::estimate_execute_order_gas_limit(data_store, @order); - gas_utils::validate_execution_fee(data_store, estimated_gas_limit, order.execution_fee); + let balance_USDC_start = IERC20Dispatcher { + contract_address: contract_address_const::<'USDC'>() + } + .balance_of(contract_address_const::<'caller'>()); - let key = nonce_utils::get_next_key(data_store); + account_utils::validate_account(account); + referral_utils::set_trader_referral_code( + referral_storage, account, params.referral_code + ); - order.touch(); + let mut initial_collateral_delta_amount = 0; + + let fee_token = token_utils::fee_token(data_store); + + let mut should_record_separate_execution_fee_transfer = true; + + if (params.order_type == OrderType::MarketSwap + || params.order_type == OrderType::LimitSwap + || params.order_type == OrderType::MarketIncrease + || params.order_type == OrderType::LimitIncrease) { + // for swaps and increase orders, the initialCollateralDeltaAmount is set based on the amount of tokens + // transferred to the orderVault + initial_collateral_delta_amount = order_vault + .record_transfer_in(params.initial_collateral_token); + if (params.initial_collateral_token == fee_token) { + if (initial_collateral_delta_amount < params.execution_fee) { + OrderError::INSUFFICIENT_WNT_AMOUNT_FOR_EXECUTION_FEE( + initial_collateral_delta_amount, params.execution_fee + ); + } + initial_collateral_delta_amount -= params.execution_fee; + should_record_separate_execution_fee_transfer = false; + } + } else if (params.order_type == OrderType::MarketDecrease + || params.order_type == OrderType::LimitDecrease + || params.order_type == OrderType::StopLossDecrease) { + // for decrease orders, the initialCollateralDeltaAmount is based on the passed in value + initial_collateral_delta_amount = params.initial_collateral_delta_amount; + } else { + OrderError::ORDER_TYPE_CANNOT_BE_CREATED(params.order_type); + } - base_order_utils::validate_non_empty_order(@order); - data_store.set_order(key, order); + if (should_record_separate_execution_fee_transfer) { + let fee_token_amount = order_vault.record_transfer_in(fee_token); + if (fee_token_amount < params.execution_fee) { + OrderError::INSUFFICIENT_WNT_AMOUNT_FOR_EXECUTION_FEE( + fee_token_amount, params.execution_fee + ); + } + params.execution_fee = fee_token_amount; + } - event_emitter.emit_order_created(key, order); + if (base_order_utils::is_position_order(params.order_type)) { + market_utils::validate_position_market(data_store, params.market); + } - key -} + // validate swap path markets + market_utils::validate_swap_path(data_store, params.swap_path); + + let mut order = Order { + key: 0, + order_type: params.order_type, + decrease_position_swap_type: params.decrease_position_swap_type, + account, + receiver: params.receiver, + callback_contract: params.callback_contract, + ui_fee_receiver: params.ui_fee_receiver, + market: params.market, + initial_collateral_token: params.initial_collateral_token, + swap_path: params.swap_path, + size_delta_usd: params.size_delta_usd, + initial_collateral_delta_amount, + trigger_price: params.trigger_price, + acceptable_price: params.acceptable_price, + execution_fee: params.execution_fee, + callback_gas_limit: params.callback_gas_limit, + min_output_amount: params.min_output_amount, + /// The block at which the order was last updated. + updated_at_block: 0, + is_long: params.is_long, + /// Whether the order is frozen. + is_frozen: false, + }; + + account_utils::validate_receiver(order.receiver); + + callback_utils::validate_callback_gas_limit(data_store, order.callback_gas_limit); + + let estimated_gas_limit = gas_utils::estimate_execute_order_gas_limit( + data_store, @order + ); + gas_utils::validate_execution_fee(data_store, estimated_gas_limit, order.execution_fee); -/// Executes an order. -/// # Arguments -/// * `params` - The parameters used to execute the order. -fn execute_order_utils(params: ExecuteOrderParams) { - // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this - // TODO GAS NOT AVAILABLE params.startingGas -= gasleft() / 63; - params.contracts.data_store.remove_order(params.key, params.order.account); + let key = nonce_utils::get_next_key(data_store); - '5. Execute Order'.print(); + order.touch(); - let balance_ETH_start = IERC20Dispatcher { contract_address: contract_address_const::<'ETH'>() } - .balance_of(contract_address_const::<'caller'>()); + base_order_utils::validate_non_empty_order(@order); + data_store.set_order(key, order); - let balance_USDC_start = IERC20Dispatcher { - contract_address: contract_address_const::<'USDC'>() - } - .balance_of(contract_address_const::<'caller'>()); + event_emitter.emit_order_created(key, order); - '5. eth start create order'.print(); - balance_ETH_start.print(); + key + } - '5. usdc start create order'.print(); - balance_USDC_start.print(); + /// Executes an order. + /// # Arguments + /// * `params` - The parameters used to execute the order. + fn execute_order_utils(ref self: ContractState, params: ExecuteOrderParams) { + // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this + // TODO GAS NOT AVAILABLE params.startingGas -= gasleft() / 63; + params.contracts.data_store.remove_order(params.key, params.order.account); - base_order_utils::validate_non_empty_order(@params.order); + '5. Execute Order'.print(); - base_order_utils::validate_order_trigger_price( - params.contracts.oracle, - params.market.index_token, - params.order.order_type, - params.order.trigger_price, - params.order.is_long - ); - 'passed validations'.print(); - let params_process = ExecuteOrderParams { - contracts: params.contracts, - key: params.key, - order: params.order, - swap_path_markets: params.swap_path_markets.clone(), - min_oracle_block_numbers: params.min_oracle_block_numbers.clone(), - max_oracle_block_numbers: params.max_oracle_block_numbers.clone(), - market: params.market, - keeper: params.keeper, - starting_gas: params.starting_gas, - secondary_order_type: params.secondary_order_type - }; + let balance_ETH_start = IERC20Dispatcher { + contract_address: contract_address_const::<'ETH'>() + } + .balance_of(contract_address_const::<'caller'>()); - let mut event_data: LogData = process_order(params_process); - // validate that internal state changes are correct before calling - // external callbacks - // if the native token was transferred to the receiver in a swap - // it may be possible to invoke external contracts before the validations - // are called + let balance_USDC_start = IERC20Dispatcher { + contract_address: contract_address_const::<'USDC'>() + } + .balance_of(contract_address_const::<'caller'>()); - let balance_ETH_after = IERC20Dispatcher { contract_address: contract_address_const::<'ETH'>() } - .balance_of(contract_address_const::<'caller'>()); - 'balance_ETH_after'.print(); - balance_ETH_after.print(); + '5. eth start create order'.print(); + balance_ETH_start.print(); - let balance_USDC_after = IERC20Dispatcher { - contract_address: contract_address_const::<'USDC'>() - } - .balance_of(contract_address_const::<'caller'>()); - 'balance_USDC_after'.print(); - balance_USDC_after.print(); - - if (params.market.market_token != contract_address_const::<0>()) { - market_utils::validate_market_token_balance_check( - params.contracts.data_store, params.market - ); - } - market_utils::validate_market_token_balance_array( - params.contracts.data_store, params.swap_path_markets - ); + '5. usdc start create order'.print(); + balance_USDC_start.print(); - params.contracts.event_emitter.emit_order_executed(params.key, params.secondary_order_type); -// callback_utils::after_order_execution(params.key, params.order, event_data); - -// the order.executionFee for liquidation / adl orders is zero -// gas costs for liquidations / adl is subsidised by the treasury -// TODO crashing -// gas_utils::pay_execution_fee_order( -// params.contracts.data_store, -// params.contracts.event_emitter, -// params.contracts.order_vault, -// params.order.execution_fee, -// params.starting_gas, -// params.keeper, -// params.order.account -// ); -} + base_order_utils::validate_non_empty_order(@params.order); -/// Process an order execution. -/// # Arguments -/// * `params` - The parameters used to process the order. -fn process_order(params: ExecuteOrderParams) -> LogData { - if (base_order_utils::is_increase_order(params.order.order_type)) { - return increase_order_utils::process_order(params); - } + base_order_utils::validate_order_trigger_price( + params.contracts.oracle, + params.market.index_token, + params.order.order_type, + params.order.trigger_price, + params.order.is_long + ); + 'passed validations'.print(); + let params_process = ExecuteOrderParams { + contracts: params.contracts, + key: params.key, + order: params.order, + swap_path_markets: params.swap_path_markets.clone(), + min_oracle_block_numbers: params.min_oracle_block_numbers.clone(), + max_oracle_block_numbers: params.max_oracle_block_numbers.clone(), + market: params.market, + keeper: params.keeper, + starting_gas: params.starting_gas, + secondary_order_type: params.secondary_order_type + }; + + // let mut event_data: LogData = self.process_order(params_process); //TODO LogData return value + self.process_order(params_process); + // validate that internal state changes are correct before calling + // external callbacks + // if the native token was transferred to the receiver in a swap + // it may be possible to invoke external contracts before the validations + // are called + + let balance_ETH_after = IERC20Dispatcher { + contract_address: contract_address_const::<'ETH'>() + } + .balance_of(contract_address_const::<'caller'>()); + 'balance_ETH_after'.print(); + balance_ETH_after.print(); - if (base_order_utils::is_decrease_order(params.order.order_type)) { - return decrease_order_utils::process_order(params); - } + let balance_USDC_after = IERC20Dispatcher { + contract_address: contract_address_const::<'USDC'>() + } + .balance_of(contract_address_const::<'caller'>()); + 'balance_USDC_after'.print(); + balance_USDC_after.print(); - if (base_order_utils::is_swap_order(params.order.order_type)) { - return swap_order_utils::process_order(params); - } + if (params.market.market_token != contract_address_const::<0>()) { + market_utils::validate_market_token_balance_check( + params.contracts.data_store, params.market + ); + } + market_utils::validate_market_token_balance_array( + params.contracts.data_store, params.swap_path_markets + ); - panic_with_felt252(OrderError::UNSUPPORTED_ORDER_TYPE) -} + params + .contracts + .event_emitter + .emit_order_executed(params.key, params.secondary_order_type); + // callback_utils::after_order_execution(params.key, params.order, event_data); + + // the order.executionFee for liquidation / adl orders is zero + // gas costs for liquidations / adl is subsidised by the treasury + // TODO crashing + // gas_utils::pay_execution_fee_order( + // params.contracts.data_store, + // params.contracts.event_emitter, + // params.contracts.order_vault, + // params.order.execution_fee, + // params.starting_gas, + // params.keeper, + // params.order.account + // ); + } -/// Cancels an order. -/// # Arguments -/// * `data_store` - The `DataStore` contract dispatcher. -/// * `event_emitter` - The `EventEmitter` contract dispatcher. -/// * `order_vault` - The `OrderVault` contract dispatcher. -/// * `key` - The key of the order to cancel -/// * `keeper` - The keeper sending the transaction. -/// * `starting_gas` - The starting gas of the transaction. -/// * `reason` - The reason for cancellation. -/// # Returns -/// Return the key of the created order. -fn cancel_order( - data_store: IDataStoreDispatcher, - event_emitter: IEventEmitterDispatcher, - order_vault: IOrderVaultDispatcher, - key: felt252, - keeper: ContractAddress, - starting_gas: u256, - reason: felt252, - reason_bytes: Array -) { - // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this - // starting_gas -= gas_left() / 63; - - let order = data_store.get_order(key); - base_order_utils::validate_non_empty_order(@order); - - data_store.remove_order(key, order.account); - - if (base_order_utils::is_increase_order(order.order_type) - || base_order_utils::is_swap_order(order.order_type)) { - if (order.initial_collateral_delta_amount > 0) { - order_vault - .transfer_out( - order.initial_collateral_token, - order.account, - order.initial_collateral_delta_amount, - ); + /// Process an order execution. + /// # Arguments + /// * `params` - The parameters used to process the order. + fn process_order(ref self: ContractState, params: ExecuteOrderParams) { + if (base_order_utils::is_increase_order(params.order.order_type)) { + self.increase_order_utils.read().process_order(params); + } else if (base_order_utils::is_decrease_order(params.order.order_type)) { + self.decrease_order_utils.read().process_order(params); + } else if (base_order_utils::is_swap_order(params.order.order_type)) { + self.swap_order_utils.read().process_order(params); + } else { + panic_with_felt252(OrderError::UNSUPPORTED_ORDER_TYPE) + } } - } - event_emitter.emit_order_cancelled(key, reason, reason_bytes.span()); + /// Cancels an order. + /// # Arguments + /// * `data_store` - The `DataStore` contract dispatcher. + /// * `event_emitter` - The `EventEmitter` contract dispatcher. + /// * `order_vault` - The `OrderVault` contract dispatcher. + /// * `key` - The key of the order to cancel + /// * `keeper` - The keeper sending the transaction. + /// * `starting_gas` - The starting gas of the transaction. + /// * `reason` - The reason for cancellation. + /// # Returns + /// Return the key of the created order. + fn cancel_order( + ref self: ContractState, + data_store: IDataStoreDispatcher, + event_emitter: IEventEmitterDispatcher, + order_vault: IOrderVaultDispatcher, + key: felt252, + keeper: ContractAddress, + starting_gas: u256, + reason: felt252, + reason_bytes: Array + ) { + // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this + // starting_gas -= gas_left() / 63; + + let order = data_store.get_order(key); + base_order_utils::validate_non_empty_order(@order); + + data_store.remove_order(key, order.account); + + if (base_order_utils::is_increase_order(order.order_type) + || base_order_utils::is_swap_order(order.order_type)) { + if (order.initial_collateral_delta_amount > 0) { + order_vault + .transfer_out( + order.initial_collateral_token, + order.account, + order.initial_collateral_delta_amount, + ); + } + } - let mut event_data: LogData = Default::default(); - callback_utils::after_order_cancellation(key, order, event_data); + event_emitter.emit_order_cancelled(key, reason, reason_bytes.span()); - gas_utils::pay_execution_fee_order( - data_store, - event_emitter, - order_vault, - order.execution_fee, - starting_gas, - keeper, - order.account - ); -} + // let mut event_data: LogData = Default::default(); + // callback_utils::after_order_cancellation(key, order, event_data); -/// Freezes an order. -/// # Arguments -/// * `data_store` - The `DataStore` contract dispatcher. -/// * `event_emitter` - The `EventEmitter` contract dispatcher. -/// * `order_vault` - The `OrderVault` contract dispatcher. -/// * `key` - The key of the order to freeze -/// * `keeper` - The keeper sending the transaction. -/// * `starting_gas` - The starting gas of the transaction. -/// * `reason` - The reason the order was frozen. -/// # Returns -/// Return the key of the created order. -fn freeze_order( - data_store: IDataStoreDispatcher, - event_emitter: IEventEmitterDispatcher, - order_vault: IOrderVaultDispatcher, - key: felt252, - keeper: ContractAddress, - starting_gas: u256, - reason: felt252, - reason_bytes: Array -) { - // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this - // startingGas -= gas_left() / 63; - - let mut order = data_store.get_order(key); - base_order_utils::validate_non_empty_order(@order); - - if (order.is_frozen) { - panic_with_felt252(OrderError::ORDER_ALREADY_FROZEN) - } + gas_utils::pay_execution_fee_order( + data_store, + event_emitter, + order_vault, + order.execution_fee, + starting_gas, + keeper, + order.account + ); + } - let execution_fee = order.execution_fee; + /// Freezes an order. + /// # Arguments + /// * `data_store` - The `DataStore` contract dispatcher. + /// * `event_emitter` - The `EventEmitter` contract dispatcher. + /// * `order_vault` - The `OrderVault` contract dispatcher. + /// * `key` - The key of the order to freeze + /// * `keeper` - The keeper sending the transaction. + /// * `starting_gas` - The starting gas of the transaction. + /// * `reason` - The reason the order was frozen. + /// # Returns + /// Return the key of the created order. + fn freeze_order( + ref self: ContractState, + data_store: IDataStoreDispatcher, + event_emitter: IEventEmitterDispatcher, + order_vault: IOrderVaultDispatcher, + key: felt252, + keeper: ContractAddress, + starting_gas: u256, + reason: felt252, + reason_bytes: Array + ) { + // 63/64 gas is forwarded to external calls, reduce the startingGas to account for this + // startingGas -= gas_left() / 63; + + let mut order = data_store.get_order(key); + base_order_utils::validate_non_empty_order(@order); + + if (order.is_frozen) { + panic_with_felt252(OrderError::ORDER_ALREADY_FROZEN) + } - order.execution_fee = 0; - order.is_frozen = true; - data_store.set_order(key, order); + let execution_fee = order.execution_fee; - event_emitter.emit_order_frozen(key, reason, reason_bytes.span()); + order.execution_fee = 0; + order.is_frozen = true; + data_store.set_order(key, order); - let mut event_data: LogData = Default::default(); - callback_utils::after_order_frozen(key, order, event_data); + event_emitter.emit_order_frozen(key, reason, reason_bytes.span()); - gas_utils::pay_execution_fee_order( - data_store, event_emitter, order_vault, execution_fee, starting_gas, keeper, order.account - ); + // let mut event_data: LogData = Default::default(); + // callback_utils::after_order_frozen(key, order, event_data); + + gas_utils::pay_execution_fee_order( + data_store, + event_emitter, + order_vault, + execution_fee, + starting_gas, + keeper, + order.account + ); + } + } } diff --git a/src/order/swap_order_utils.cairo b/src/order/swap_order_utils.cairo index 888d8bb7..d471352d 100644 --- a/src/order/swap_order_utils.cairo +++ b/src/order/swap_order_utils.cairo @@ -1,3 +1,7 @@ +// ************************************************************************* +// IMPORTS +// ************************************************************************* + // Core lib imports. use starknet::{ContractAddress, contract_address_const}; @@ -10,8 +14,8 @@ use satoru::oracle::oracle_utils; use satoru::utils::arrays::are_gte_u64; use satoru::swap::swap_utils; use satoru::event::event_utils::{ - LogData, LogDataTrait, Felt252IntoContractAddress, ContractAddressDictValue, I256252DictValue, - U256252DictValue, U256IntoFelt252 + Felt252IntoContractAddress, ContractAddressDictValue, I256252DictValue, U256252DictValue, + U256IntoFelt252 }; use satoru::utils::serializable_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; use satoru::order::error::OrderError; @@ -20,96 +24,157 @@ use satoru::utils::span32::{Span32, DefaultSpan32}; use satoru::oracle::error::OracleError; use satoru::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; -fn process_order(params: ExecuteOrderParams) -> LogData { - '6. Process Order'.print(); - if (params.order.market.is_non_zero()) { - panic(array![OrderError::UNEXPECTED_MARKET]); - } - // validate_oracle_block_numbers( - // params.min_oracle_block_numbers.span(), - // params.max_oracle_block_numbers.span(), - // params.order.order_type, - // params.order.updated_at_block - // ); - let balance_ETH_start = IERC20Dispatcher { contract_address: contract_address_const::<'ETH'>() } - .balance_of(contract_address_const::<'caller'>()); - - let balance_usdc_start = IERC20Dispatcher { - contract_address: contract_address_const::<'USDC'>() - } - .balance_of(contract_address_const::<'caller'>()); - - '6. eth start process order'.print(); - balance_ETH_start.print(); - - '6. usdc start process order'.print(); - balance_usdc_start.print(); - - let (output_token, output_amount) = swap_utils::swap( - @swap_utils::SwapParams { - data_store: params.contracts.data_store, - event_emitter: params.contracts.event_emitter, - oracle: params.contracts.oracle, - bank: IBankDispatcher { - contract_address: params.contracts.order_vault.contract_address - }, - key: params.key, - token_in: params.order.initial_collateral_token, - amount_in: params.order.initial_collateral_delta_amount, - swap_path_markets: params.swap_path_markets.span(), - min_output_amount: params.order.min_output_amount, - receiver: params.order.receiver, - ui_fee_receiver: params.order.ui_fee_receiver, - } +// ************************************************************************* +// Interface of the `OrderUtils` contract. +// ************************************************************************* +#[starknet::interface] +trait ISwapOrderUtils { + fn process_order(ref self: TContractState, params: ExecuteOrderParams); + + /// Validate the oracle block numbers used for the prices in the oracle. + /// # Arguments + /// * `min_oracle_block_numbers` - The min oracle block numbers. + /// * `max_oracle_block_numbers` - The max oracle block numbers. + /// * `order_type` - The order type. + /// * `order_updated_at_block` - the block at which the order was last updated. + fn validate_oracle_block_numbers( + ref self: TContractState, + min_oracle_block_numbers: Span, + max_oracle_block_numbers: Span, + order_type: OrderType, + order_updated_at_block: u64 ); +} +#[starknet::contract] +mod SwapOrderUtils { + // Core lib imports. + use starknet::{ContractAddress, contract_address_const}; + + use debug::PrintTrait; + + // Local imports. + use satoru::order::base_order_utils::ExecuteOrderParams; + use satoru::order::order::OrderType; + use satoru::oracle::oracle_utils; + use satoru::utils::arrays::are_gte_u64; + use satoru::swap::swap_utils; + use satoru::event::event_utils::{ + Felt252IntoContractAddress, ContractAddressDictValue, I256252DictValue, U256252DictValue, + U256IntoFelt252 + }; + use satoru::utils::serializable_dict::{SerializableFelt252Dict, SerializableFelt252DictTrait}; + use satoru::order::error::OrderError; + use satoru::bank::bank::{IBankDispatcher, IBankDispatcherTrait}; + use satoru::utils::span32::{Span32, DefaultSpan32}; + use satoru::oracle::error::OracleError; + use satoru::token::erc20::interface::{IERC20Dispatcher, IERC20DispatcherTrait}; + + #[storage] + struct Storage {} + + // ************************************************************************* + // EXTERNAL FUNCTIONS + // ************************************************************************* + #[abi(embed_v0)] + impl SwapOrderUtilsImpl of super::ISwapOrderUtils { + fn process_order(ref self: ContractState, params: ExecuteOrderParams) { + '6. Process Order'.print(); + if (params.order.market.is_non_zero()) { + panic(array![OrderError::UNEXPECTED_MARKET]); + } + // validate_oracle_block_numbers( + // params.min_oracle_block_numbers.span(), + // params.max_oracle_block_numbers.span(), + // params.order.order_type, + // params.order.updated_at_block + // ); + let balance_ETH_start = IERC20Dispatcher { + contract_address: contract_address_const::<'ETH'>() + } + .balance_of(contract_address_const::<'caller'>()); + + let balance_usdc_start = IERC20Dispatcher { + contract_address: contract_address_const::<'USDC'>() + } + .balance_of(contract_address_const::<'caller'>()); + + '6. eth start process order'.print(); + balance_ETH_start.print(); + + '6. usdc start process order'.print(); + balance_usdc_start.print(); + + let (output_token, output_amount) = swap_utils::swap( + @swap_utils::SwapParams { + data_store: params.contracts.data_store, + event_emitter: params.contracts.event_emitter, + oracle: params.contracts.oracle, + bank: IBankDispatcher { + contract_address: params.contracts.order_vault.contract_address + }, + key: params.key, + token_in: params.order.initial_collateral_token, + amount_in: params.order.initial_collateral_delta_amount, + swap_path_markets: params.swap_path_markets.span(), + min_output_amount: params.order.min_output_amount, + receiver: params.order.receiver, + ui_fee_receiver: params.order.ui_fee_receiver, + } + ); - let mut log_data: LogData = Default::default(); - - log_data.address_dict.insert_single('output_token', output_token); - log_data.uint_dict.insert_single('output_amount', output_amount); + // let mut log_data: LogData = Default::default(); - let balance_ETH_end = IERC20Dispatcher { contract_address: contract_address_const::<'ETH'>() } - .balance_of(contract_address_const::<'caller'>()); + // log_data.address_dict.insert_single('output_token', output_token); + // log_data.uint_dict.insert_single('output_amount', output_amount); - let balance_usdc_end = IERC20Dispatcher { contract_address: contract_address_const::<'USDC'>() } - .balance_of(contract_address_const::<'caller'>()); + let balance_ETH_end = IERC20Dispatcher { + contract_address: contract_address_const::<'ETH'>() + } + .balance_of(contract_address_const::<'caller'>()); - '6. eth end process order'.print(); - balance_ETH_end.print(); + let balance_usdc_end = IERC20Dispatcher { + contract_address: contract_address_const::<'USDC'>() + } + .balance_of(contract_address_const::<'caller'>()); - '6. usdc end process order'.print(); - balance_usdc_end.print(); - '------------------------'.print(); + '6. eth end process order'.print(); + balance_ETH_end.print(); - log_data -} + '6. usdc end process order'.print(); + balance_usdc_end.print(); + '------------------------'.print(); + // log_data + } -/// Validate the oracle block numbers used for the prices in the oracle. -/// # Arguments -/// * `min_oracle_block_numbers` - The min oracle block numbers. -/// * `max_oracle_block_numbers` - The max oracle block numbers. -/// * `order_type` - The order type. -/// * `order_updated_at_block` - the block at which the order was last updated. -fn validate_oracle_block_numbers( - min_oracle_block_numbers: Span, - max_oracle_block_numbers: Span, - order_type: OrderType, - order_updated_at_block: u64 -) { - if (order_type == OrderType::MarketSwap) { - oracle_utils::validate_block_number_within_range( - min_oracle_block_numbers, max_oracle_block_numbers, order_updated_at_block - ); - return; - } - if (order_type == OrderType::LimitSwap) { - if (!are_gte_u64(min_oracle_block_numbers, order_updated_at_block)) { - OracleError::ORACLE_BLOCK_NUMBERS_ARE_SMALLER_THAN_REQUIRED( - min_oracle_block_numbers, order_updated_at_block - ); + /// Validate the oracle block numbers used for the prices in the oracle. + /// # Arguments + /// * `min_oracle_block_numbers` - The min oracle block numbers. + /// * `max_oracle_block_numbers` - The max oracle block numbers. + /// * `order_type` - The order type. + /// * `order_updated_at_block` - the block at which the order was last updated. + fn validate_oracle_block_numbers( + ref self: ContractState, + min_oracle_block_numbers: Span, + max_oracle_block_numbers: Span, + order_type: OrderType, + order_updated_at_block: u64 + ) { + if (order_type == OrderType::MarketSwap) { + oracle_utils::validate_block_number_within_range( + min_oracle_block_numbers, max_oracle_block_numbers, order_updated_at_block + ); + return; + } + if (order_type == OrderType::LimitSwap) { + if (!are_gte_u64(min_oracle_block_numbers, order_updated_at_block)) { + OracleError::ORACLE_BLOCK_NUMBERS_ARE_SMALLER_THAN_REQUIRED( + min_oracle_block_numbers, order_updated_at_block + ); + } + return; + } + panic(array![OrderError::UNSUPPORTED_ORDER_TYPE]); } - return; } - panic(array![OrderError::UNSUPPORTED_ORDER_TYPE]); } diff --git a/src/position/decrease_position_utils.cairo b/src/position/decrease_position_utils.cairo index 320d93a9..860cee9e 100644 --- a/src/position/decrease_position_utils.cairo +++ b/src/position/decrease_position_utils.cairo @@ -249,10 +249,13 @@ fn decrease_position(mut params: UpdatePositionParams) -> DecreasePositionResult 'size otk bef'.print(); params.position.size_in_tokens.print(); params.position.size_in_usd = cache.next_position_size_in_usd; - params.position.size_in_tokens -= values.remaining_collateral_amount; //TODO has to be : values.size_delta_in_tokens + params + .position + .size_in_tokens -= values + .remaining_collateral_amount; //TODO has to be : values.size_delta_in_tokens params.position.collateral_amount = values.remaining_collateral_amount; params.position.decreased_at_block = starknet::info::get_block_number(); - + 'new position detials'.print(); values.size_delta_in_tokens.print(); params.position.size_in_usd.print(); diff --git a/tests/integration/swap_test.cairo b/tests/integration/swap_test.cairo index 07024a23..c536be4c 100644 --- a/tests/integration/swap_test.cairo +++ b/tests/integration/swap_test.cairo @@ -17,6 +17,7 @@ use snforge_std::{declare, start_prank, stop_prank, start_roll, ContractClassTra // Local imports. use satoru::data::data_store::{IDataStoreDispatcher, IDataStoreDispatcherTrait}; use satoru::role::role_store::{IRoleStoreDispatcher, IRoleStoreDispatcherTrait}; +use satoru::order::order_utils::{IOrderUtilsDispatcher, IOrderUtilsDispatcherTrait}; use satoru::market::market_factory::{IMarketFactoryDispatcher, IMarketFactoryDispatcherTrait}; use satoru::event::event_emitter::{IEventEmitterDispatcher, IEventEmitterDispatcherTrait}; use satoru::deposit::deposit_vault::{IDepositVaultDispatcher, IDepositVaultDispatcherTrait}; @@ -604,6 +605,14 @@ fn setup_contracts() -> ( let swap_handler_address = deploy_swap_handler_address(role_store_address, data_store_address); let referral_storage_address = deploy_referral_storage(event_emitter_address); + + let increase_order_address = deploy_increase_order(); + let decrease_order_address = deploy_decrease_order(); + let swap_order_address = deploy_swap_order(); + + let order_utils_address = deploy_order_utils( + increase_order_address, decrease_order_address, swap_order_address + ); let order_handler_address = deploy_order_handler( data_store_address, role_store_address, @@ -611,7 +620,8 @@ fn setup_contracts() -> ( order_vault_address, oracle_address, swap_handler_address, - referral_storage_address + referral_storage_address, + order_utils_address ); let order_handler = IOrderHandlerDispatcher { contract_address: order_handler_address }; @@ -825,7 +835,8 @@ fn deploy_order_handler( order_vault_address: ContractAddress, oracle_address: ContractAddress, swap_handler_address: ContractAddress, - referral_storage_address: ContractAddress + referral_storage_address: ContractAddress, + order_utils_address: ContractAddress ) -> ContractAddress { let contract = declare('OrderHandler'); let caller_address: ContractAddress = contract_address_const::<'caller'>(); @@ -838,7 +849,8 @@ fn deploy_order_handler( order_vault_address.into(), oracle_address.into(), swap_handler_address.into(), - referral_storage_address.into() + referral_storage_address.into(), + order_utils_address.into() ]; contract.deploy_at(@constructor_calldata, deployed_contract_address).unwrap() } @@ -898,6 +910,50 @@ fn deploy_order_vault( tests_lib::deploy_mock_contract(contract, @constructor_calldata) } +fn deploy_increase_order() -> ContractAddress { + let contract = declare('IncreaseOrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'increase_order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract.deploy_at(@array![], deployed_contract_address).unwrap() +} +fn deploy_decrease_order() -> ContractAddress { + let contract = declare('DecreaseOrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'decrease_order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract.deploy_at(@array![], deployed_contract_address).unwrap() +} +fn deploy_swap_order() -> ContractAddress { + let contract = declare('SwapOrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'swap_order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract.deploy_at(@array![], deployed_contract_address).unwrap() +} + + +fn deploy_order_utils( + increase_order_address: ContractAddress, + decrease_order_address: ContractAddress, + swap_order_address: ContractAddress, +) -> ContractAddress { + let contract = declare('OrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract + .deploy_at( + @array![ + increase_order_address.into(), + decrease_order_address.into(), + swap_order_address.into() + ], + deployed_contract_address + ) + .unwrap() +} + fn deploy_bank( data_store_address: ContractAddress, role_store_address: ContractAddress, ) -> ContractAddress { diff --git a/tests/integration/test_deposit_withdrawal.cairo b/tests/integration/test_deposit_withdrawal.cairo index 339fd6cd..9d1b6ac4 100644 --- a/tests/integration/test_deposit_withdrawal.cairo +++ b/tests/integration/test_deposit_withdrawal.cairo @@ -17,6 +17,7 @@ use snforge_std::{declare, start_prank, stop_prank, start_roll, ContractClassTra // Local imports. use satoru::data::data_store::{IDataStoreDispatcher, IDataStoreDispatcherTrait}; use satoru::role::role_store::{IRoleStoreDispatcher, IRoleStoreDispatcherTrait}; +use satoru::order::order_utils::{IOrderUtilsDispatcher, IOrderUtilsDispatcherTrait}; use satoru::market::market_factory::{IMarketFactoryDispatcher, IMarketFactoryDispatcherTrait}; use satoru::event::event_emitter::{IEventEmitterDispatcher, IEventEmitterDispatcherTrait}; use satoru::deposit::deposit_vault::{IDepositVaultDispatcher, IDepositVaultDispatcherTrait}; @@ -1163,6 +1164,14 @@ fn setup_contracts() -> ( let swap_handler_address = deploy_swap_handler_address(role_store_address, data_store_address); let referral_storage_address = deploy_referral_storage(event_emitter_address); + + let increase_order_address = deploy_increase_order(); + let decrease_order_address = deploy_decrease_order(); + let swap_order_address = deploy_swap_order(); + + let order_utils_address = deploy_order_utils( + increase_order_address, decrease_order_address, swap_order_address + ); let order_handler_address = deploy_order_handler( data_store_address, role_store_address, @@ -1170,7 +1179,8 @@ fn setup_contracts() -> ( order_vault_address, oracle_address, swap_handler_address, - referral_storage_address + referral_storage_address, + order_utils_address ); let order_handler = IOrderHandlerDispatcher { contract_address: order_handler_address }; @@ -1360,6 +1370,50 @@ fn deploy_deposit_vault( .unwrap() } +fn deploy_increase_order() -> ContractAddress { + let contract = declare('IncreaseOrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'increase_order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract.deploy_at(@array![], deployed_contract_address).unwrap() +} +fn deploy_decrease_order() -> ContractAddress { + let contract = declare('DecreaseOrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'decrease_order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract.deploy_at(@array![], deployed_contract_address).unwrap() +} +fn deploy_swap_order() -> ContractAddress { + let contract = declare('SwapOrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'swap_order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract.deploy_at(@array![], deployed_contract_address).unwrap() +} + + +fn deploy_order_utils( + increase_order_address: ContractAddress, + decrease_order_address: ContractAddress, + swap_order_address: ContractAddress, +) -> ContractAddress { + let contract = declare('OrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract + .deploy_at( + @array![ + increase_order_address.into(), + decrease_order_address.into(), + swap_order_address.into() + ], + deployed_contract_address + ) + .unwrap() +} + fn deploy_withdrawal_handler( data_store_address: ContractAddress, role_store_address: ContractAddress, @@ -1399,7 +1453,8 @@ fn deploy_order_handler( order_vault_address: ContractAddress, oracle_address: ContractAddress, swap_handler_address: ContractAddress, - referral_storage_address: ContractAddress + referral_storage_address: ContractAddress, + order_utils_address: ContractAddress ) -> ContractAddress { let contract = declare('OrderHandler'); let caller_address: ContractAddress = contract_address_const::<'caller'>(); @@ -1412,7 +1467,8 @@ fn deploy_order_handler( order_vault_address.into(), oracle_address.into(), swap_handler_address.into(), - referral_storage_address.into() + referral_storage_address.into(), + order_utils_address.into() ]; contract.deploy_at(@constructor_calldata, deployed_contract_address).unwrap() } diff --git a/tests/integration/test_long_integration.cairo b/tests/integration/test_long_integration.cairo index 6ef3f399..fa385992 100644 --- a/tests/integration/test_long_integration.cairo +++ b/tests/integration/test_long_integration.cairo @@ -17,6 +17,7 @@ use snforge_std::{declare, start_prank, stop_prank, start_roll, ContractClassTra // Local imports. use satoru::data::data_store::{IDataStoreDispatcher, IDataStoreDispatcherTrait}; use satoru::role::role_store::{IRoleStoreDispatcher, IRoleStoreDispatcherTrait}; +use satoru::order::order_utils::{IOrderUtilsDispatcher, IOrderUtilsDispatcherTrait}; use satoru::market::market_factory::{IMarketFactoryDispatcher, IMarketFactoryDispatcherTrait}; use satoru::event::event_emitter::{IEventEmitterDispatcher, IEventEmitterDispatcherTrait}; use satoru::deposit::deposit_vault::{IDepositVaultDispatcher, IDepositVaultDispatcherTrait}; @@ -242,7 +243,6 @@ fn test_long_market_integration() { let max_key_open_interest = keys::max_open_interest_key(market.market_token, true); data_store.set_u256(max_key_open_interest, 10000000); - start_prank(contract_address_const::<'ETH'>(), caller_address); // Send token to order_vault in multicall with create_order IERC20Dispatcher { contract_address: contract_address_const::<'ETH'>() } @@ -380,7 +380,9 @@ fn test_long_market_integration() { //////////////////////////////////// CLOSING POSITION ////////////////////////////////////// 'CLOOOOSE POSITION'.print(); - let balance_of_mkt_before = IERC20Dispatcher { contract_address: contract_address_const::<'USDC'>() } + let balance_of_mkt_before = IERC20Dispatcher { + contract_address: contract_address_const::<'USDC'>() + } .balance_of(caller_address); 'balance of mkt before'.print(); balance_of_mkt_before.print(); @@ -462,7 +464,9 @@ fn test_long_market_integration() { 'size in usd'.print(); first_position_dec.size_in_usd.print(); - let balance_of_mkt_after = IERC20Dispatcher { contract_address: contract_address_const::<'USDC'>() } + let balance_of_mkt_after = IERC20Dispatcher { + contract_address: contract_address_const::<'USDC'>() + } .balance_of(caller_address); 'balance of mkt after'.print(); balance_of_mkt_after.print(); @@ -714,6 +718,15 @@ fn setup_contracts() -> ( let swap_handler_address = deploy_swap_handler_address(role_store_address, data_store_address); let referral_storage_address = deploy_referral_storage(event_emitter_address); + + let increase_order_address = deploy_increase_order(); + let decrease_order_address = deploy_decrease_order(); + let swap_order_address = deploy_swap_order(); + + let order_utils_address = deploy_order_utils( + increase_order_address, decrease_order_address, swap_order_address + ); + let order_handler_address = deploy_order_handler( data_store_address, role_store_address, @@ -721,7 +734,8 @@ fn setup_contracts() -> ( order_vault_address, oracle_address, swap_handler_address, - referral_storage_address + referral_storage_address, + order_utils_address ); let order_handler = IOrderHandlerDispatcher { contract_address: order_handler_address }; @@ -950,7 +964,8 @@ fn deploy_order_handler( order_vault_address: ContractAddress, oracle_address: ContractAddress, swap_handler_address: ContractAddress, - referral_storage_address: ContractAddress + referral_storage_address: ContractAddress, + order_utils_address: ContractAddress ) -> ContractAddress { let contract = declare('OrderHandler'); let caller_address: ContractAddress = contract_address_const::<'caller'>(); @@ -963,7 +978,8 @@ fn deploy_order_handler( order_vault_address.into(), oracle_address.into(), swap_handler_address.into(), - referral_storage_address.into() + referral_storage_address.into(), + order_utils_address.into() ]; contract.deploy_at(@constructor_calldata, deployed_contract_address).unwrap() } @@ -1023,6 +1039,50 @@ fn deploy_order_vault( tests_lib::deploy_mock_contract(contract, @constructor_calldata) } +fn deploy_increase_order() -> ContractAddress { + let contract = declare('IncreaseOrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'increase_order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract.deploy_at(@array![], deployed_contract_address).unwrap() +} +fn deploy_decrease_order() -> ContractAddress { + let contract = declare('DecreaseOrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'decrease_order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract.deploy_at(@array![], deployed_contract_address).unwrap() +} +fn deploy_swap_order() -> ContractAddress { + let contract = declare('SwapOrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'swap_order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract.deploy_at(@array![], deployed_contract_address).unwrap() +} + + +fn deploy_order_utils( + increase_order_address: ContractAddress, + decrease_order_address: ContractAddress, + swap_order_address: ContractAddress, +) -> ContractAddress { + let contract = declare('OrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract + .deploy_at( + @array![ + increase_order_address.into(), + decrease_order_address.into(), + swap_order_address.into() + ], + deployed_contract_address + ) + .unwrap() +} + fn deploy_bank( data_store_address: ContractAddress, role_store_address: ContractAddress, ) -> ContractAddress { diff --git a/tests/integration/test_short_integration.cairo b/tests/integration/test_short_integration.cairo index 0d6cf86e..dff36b8b 100644 --- a/tests/integration/test_short_integration.cairo +++ b/tests/integration/test_short_integration.cairo @@ -17,6 +17,7 @@ use snforge_std::{declare, start_prank, stop_prank, start_roll, ContractClassTra // Local imports. use satoru::data::data_store::{IDataStoreDispatcher, IDataStoreDispatcherTrait}; use satoru::role::role_store::{IRoleStoreDispatcher, IRoleStoreDispatcherTrait}; +use satoru::order::order_utils::{IOrderUtilsDispatcher, IOrderUtilsDispatcherTrait}; use satoru::market::market_factory::{IMarketFactoryDispatcher, IMarketFactoryDispatcherTrait}; use satoru::event::event_emitter::{IEventEmitterDispatcher, IEventEmitterDispatcherTrait}; use satoru::deposit::deposit_vault::{IDepositVaultDispatcher, IDepositVaultDispatcherTrait}; @@ -598,6 +599,14 @@ fn setup_contracts() -> ( let swap_handler_address = deploy_swap_handler_address(role_store_address, data_store_address); let referral_storage_address = deploy_referral_storage(event_emitter_address); + + let increase_order_address = deploy_increase_order(); + let decrease_order_address = deploy_decrease_order(); + let swap_order_address = deploy_swap_order(); + + let order_utils_address = deploy_order_utils( + increase_order_address, decrease_order_address, swap_order_address + ); let order_handler_address = deploy_order_handler( data_store_address, role_store_address, @@ -605,7 +614,8 @@ fn setup_contracts() -> ( order_vault_address, oracle_address, swap_handler_address, - referral_storage_address + referral_storage_address, + order_utils_address ); let order_handler = IOrderHandlerDispatcher { contract_address: order_handler_address }; @@ -834,7 +844,8 @@ fn deploy_order_handler( order_vault_address: ContractAddress, oracle_address: ContractAddress, swap_handler_address: ContractAddress, - referral_storage_address: ContractAddress + referral_storage_address: ContractAddress, + order_utils_address: ContractAddress ) -> ContractAddress { let contract = declare('OrderHandler'); let caller_address: ContractAddress = contract_address_const::<'caller'>(); @@ -847,7 +858,8 @@ fn deploy_order_handler( order_vault_address.into(), oracle_address.into(), swap_handler_address.into(), - referral_storage_address.into() + referral_storage_address.into(), + order_utils_address.into() ]; contract.deploy_at(@constructor_calldata, deployed_contract_address).unwrap() } @@ -907,6 +919,50 @@ fn deploy_order_vault( tests_lib::deploy_mock_contract(contract, @constructor_calldata) } +fn deploy_increase_order() -> ContractAddress { + let contract = declare('IncreaseOrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'increase_order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract.deploy_at(@array![], deployed_contract_address).unwrap() +} +fn deploy_decrease_order() -> ContractAddress { + let contract = declare('DecreaseOrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'decrease_order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract.deploy_at(@array![], deployed_contract_address).unwrap() +} +fn deploy_swap_order() -> ContractAddress { + let contract = declare('SwapOrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'swap_order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract.deploy_at(@array![], deployed_contract_address).unwrap() +} + + +fn deploy_order_utils( + increase_order_address: ContractAddress, + decrease_order_address: ContractAddress, + swap_order_address: ContractAddress, +) -> ContractAddress { + let contract = declare('OrderUtils'); + let caller_address: ContractAddress = contract_address_const::<'caller'>(); + let deployed_contract_address = contract_address_const::<'order_utils'>(); + start_prank(deployed_contract_address, caller_address); + contract + .deploy_at( + @array![ + increase_order_address.into(), + decrease_order_address.into(), + swap_order_address.into() + ], + deployed_contract_address + ) + .unwrap() +} + fn deploy_bank( data_store_address: ContractAddress, role_store_address: ContractAddress, ) -> ContractAddress { diff --git a/tests/lib.cairo b/tests/lib.cairo index c3d00f84..cec9321a 100644 --- a/tests/lib.cairo +++ b/tests/lib.cairo @@ -42,11 +42,11 @@ mod event { mod test_event_utils; } mod exchange { - mod test_liquidation_handler; + // mod test_liquidation_handler; mod test_withdrawal_handler; mod test_deposit_handler; mod test_exchange_utils; - mod test_base_order_handler; +// mod test_base_order_handler; } mod feature { mod test_feature_utils; @@ -68,7 +68,7 @@ mod oracle { } mod order { mod test_base_order_utils; - mod test_increase_order_utils; + // mod test_increase_order_utils; mod test_order; } mod position { @@ -124,6 +124,6 @@ mod integration { mod test_deposit_withdrawal; mod test_long_integration; mod test_short_integration; - mod test_swap_integration; + // mod test_swap_integration; mod swap_test; }