```\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport "forge-std/Test.sol";\nimport "../contracts/role/RoleStore.sol";\nimport "../contracts/router/ExchangeRouter.sol";\nimport "../contracts/data/DataStore.sol";\nimport "../contracts/referral/ReferralStorage.sol";\n\nimport "../contracts/token/IWNT.sol";\nimport "../contracts/token/WNT.sol";\nimport "../contracts/token/SOLToken.sol";\nimport "../contracts/token/USDC.sol";\nimport "../contracts/token/tokenA.sol";\nimport "../contracts/token/tokenB.sol";\nimport "../contracts/token/tokenC.sol";\n\nimport "../contracts/market/MarketFactory.sol";\nimport "../contracts/deposit/DepositUtils.sol";\nimport "../contracts/oracle/OracleUtils.sol";\nimport "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";\nimport "../contracts/withdrawal/WithdrawalUtils.sol";\nimport "../contracts/order/Order.sol";\nimport "../contracts/order/BaseOrderUtils.sol";\nimport "../contracts/price/Price.sol";\nimport "../contracts/utils/Debug.sol";\nimport "../contracts/position/Position.sol";\nimport "../contracts/exchange/LiquidationHandler.sol";\nimport "../contracts/utils/Calc.sol";\nimport "@openzeppelin/contracts/utils/math/SignedMath.sol";\nimport "@openzeppelin/contracts/utils/math/SafeCast.sol";\n\n\ncontract CounterTest is Test, Debug{\n     using SignedMath for int256;\n    using SafeCast for uint256;\n\n\n    WNT _wnt; \n    USDC _usdc;\n    SOLToken _sol;\n    tokenA _tokenA;\n    tokenB _tokenB;\n    tokenC _tokenC;\n\n    RoleStore _roleStore;\n    Router _router;\n    DataStore _dataStore;\n    EventEmitter _eventEmitter;\n    DepositVault _depositVault;\n    OracleStore _oracleStore; \n    Oracle _oracle;\n    DepositHandler _depositHandler;\n    WithdrawalVault _withdrawalVault;\n    WithdrawalHandler _withdrawalHandler;\n    OrderHandler _orderHandler;\n    SwapHandler _swapHandler;\n    LiquidationHandler _liquidationHandler;\n    ReferralStorage _referralStorage;\n    OrderVault _orderVault;\n    ExchangeRouter _erouter;\n    MarketFactory _marketFactory;\n    Market.Props _marketProps1;\n    Market.Props _marketPropsAB;\n    Market.Props _marketPropsBC;\n    Market.Props _marketPropsCwnt;\n    \n    \n    address depositor1;\n    address depositor2;\n    address depositor3;\n    address uiFeeReceiver = address(333);\n\n\n    function testGetFundingAmountPerSizeDelta() public{\n        uint result = MarketUtils.getFundingAmountPerSizeDelta(2e15, 1e15+1, true);\n        console2.log("result: %d", result);\n        uint256 correctResult = 2e15 * 1e15 * 1e30 + 1e15; // this is a real round up\n        correctResult = correctResult/(1e15+1);\n        console2.log("correctResult: %d", correctResult);\n        assertTrue(result  == 1e15 * 1e30);\n    }\n\n   \n\n    function setUp() public {\n        _wnt = new WNT();\n        _usdc = new USDC();\n        _sol = new SOLToken();\n        _tokenA = new tokenA();\n        _tokenB = new tokenB();\n         _tokenC = new tokenC();\n        \n\n\n         _roleStore = new RoleStore();\n         _router = new Router(_roleStore);\n         _dataStore = new DataStore(_roleStore);\n         \n         _eventEmitter= new EventEmitter(_roleStore);\n        _depositVault = new DepositVault(_roleStore, _dataStore);\n        _oracleStore = new OracleStore(_roleStore, _eventEmitter);\n        _oracle = new Oracle(_roleStore, _oracleStore);\n        console2.logString("_oracle:"); console2.logAddress(address(_oracle));\n        \n         _depositHandler = new DepositHandler(_roleStore, _dataStore, _eventEmitter, _depositVault, _oracle);\n         console2.logString("_depositHandler:"); console2.logAddress(address(_depositHandler));\n        \n\n       _withdrawalVault = new WithdrawalVault(_roleStore, _dataStore);\n        _withdrawalHandler = new WithdrawalHandler(_roleStore, _dataStore, _eventEmitter, _withdrawalVault, _oracle);\n \n \n        _swapHandler = new SwapHandler(_roleStore);\n        _orderVault = new OrderVault(_roleStore, _dataStore);\n        _referralStorage = new ReferralStorage();\n\n\n        \n        _orderHandler = new OrderHandler(_roleStore, _dataStore, _eventEmitter, _orderVault, _oracle, _swapHandler, _referralStorage);  \n        _erouter = new ExchangeRouter(_router, _roleStore, _dataStore, _eventEmitter, _depositHandler, _withdrawalHandler, _orderHandler);\n         console2.logString("_erouter:"); console2.logAddress(address(_erouter));\n         _liquidationHandler = new LiquidationHandler(_roleStore, _dataStore, _eventEmitter, _orderVault, _oracle, _swapHandler, _referralStorage);\n       \n        _referralStorage.setHandler(address(_orderHandler), true);  \n\n        /* set myself as the controller so that I can set the address of WNT (wrapped native token contracdt) */\n        _roleStore.grantRole(address(this), Role.CONTROLLER);\n        _roleStore.grantRole(address(this), Role.MARKET_KEEPER);\n        \n        _dataStore.setUint(Keys.MAX_SWAP_PATH_LENGTH, 5); // at most 5 markets in the path\n        \n        _dataStore.setAddress(Keys.WNT, address(_wnt));\n\n        /* set the token transfer gas limit for wnt as 3200 */\n        _dataStore.setUint(Keys.tokenTransferGasLimit(address(_wnt)), 32000);  \n        _dataStore.setUint(Keys.tokenTransferGasLimit(address(_usdc)), 32000);  \n             \n\n        /* create a market (SQL, WNT, ETH, USDC) */\n        _marketFactory = new MarketFactory(_roleStore, _dataStore, _eventEmitter);\n        console2.logString("_marketFactory:"); console2.logAddress(address(_marketFactory));\n        _roleStore.grantRole(address(_marketFactory), Role.CONTROLLER); // to save a market's props\n        _roleStore.grantRole(address(_erouter), Role.CONTROLLER); \n        _roleStore.grantRole(address(_depositHandler), Role.CONTROLLER); \n        _roleStore.grantRole(address(_withdrawalHandler), Role.CONTROLLER); \n         _roleStore.grantRole(address(_swapHandler), Role.CONTROLLER);\n        _roleStore.grantRole(address(_orderHandler), Role.CONTROLLER);   \n        _roleStore.grantRole(address(_liquidationHandler), Role.CONTROLLER);     \n        _roleStore.grantRole(address(_oracleStore), Role.CONTROLLER); // so it can call EventEmitter\n        _roleStore.grantRole(address(_oracle), Role.CONTROLLER); // so it can call EventEmitter\n        _roleStore.grantRole(address(this), Role.ORDER_KEEPER);\n        _roleStore.grantRole(address(this), Role.LIQUIDATION_KEEPER);\n\n        \n        _marketProps1 = _marketFactory.createMarket(address(_sol), address(_wnt), address(_usdc), keccak256(abi.encode("sol-wnt-usdc"))); \n        _marketPropsAB = _marketFactory.createMarket(address(0), address(_tokenA), address(_tokenB), keccak256(abi.encode("swap-tokenA-tokenB"))); \n        _marketPropsBC = _marketFactory.createMarket(address(0), address(_tokenB), address(_tokenC), keccak256(abi.encode("swap-tokenB-tokenC"))); \n        _marketPropsCwnt = _marketFactory.createMarket(address(0), address(_tokenC), address(_wnt), keccak256(abi.encode("swap-tokenC-wnt"))); \n        \n        \n        _dataStore.setUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(_marketProps1.marketToken, true), 1e25);\n        _dataStore.setUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(_marketProps1.marketToken, false), 1e25);\n        \n        // see fees for the market\n        _dataStore.setUint(Keys.swapFeeFactorKey(_marketProps1.marketToken), 0.05e30); // 5%\n        _dataStore.setUint(Keys.SWAP_FEE_RECEIVER_FACTOR, 0.5e30);\n        _dataStore.setUint(Keys.positionFeeFactorKey(_marketProps1.marketToken), 0.00001234e30); // 2%\n        _dataStore.setUint(Keys.POSITION_FEE_RECEIVER_FACTOR, 0.15e30);\n         _dataStore.setUint(Keys.MAX_UI_FEE_FACTOR, 0.01e30);\n        _dataStore.setUint(Keys.uiFeeFactorKey(uiFeeReceiver), 0.01e30); // only when this is set, one can receive ui fee, so stealing is not easy\n        _dataStore.setInt(Keys.poolAmountAdjustmentKey(_marketProps1.marketToken, _marketProps1.longToken), 1);\n        _dataStore.setInt(Keys.poolAmountAdjustmentKey(_marketProps1.marketToken, _marketProps1.shortToken), 1);\n        _dataStore.setUint(Keys.swapImpactExponentFactorKey(_marketProps1.marketToken), 10e28);\n        _dataStore.setUint(Keys.swapImpactFactorKey(_marketProps1.marketToken, true), 0.99e30);\n        _dataStore.setUint(Keys.swapImpactFactorKey(_marketProps1.marketToken, false), 0.99e30);\n\n       \n        \n        \n        // set gas limit to transfer a token\n        _dataStore.setUint(Keys.tokenTransferGasLimit(address(_sol)), 32000);  \n        _dataStore.setUint(Keys.tokenTransferGasLimit(address(_wnt)), 32000);  \n        _dataStore.setUint(Keys.tokenTransferGasLimit(address(_usdc)), 32000);  \n        _dataStore.setUint(Keys.tokenTransferGasLimit(address(_tokenA)), 32000);  \n        _dataStore.setUint(Keys.tokenTransferGasLimit(address(_tokenB)), 32000);  \n        _dataStore.setUint(Keys.tokenTransferGasLimit(address(_tokenC)), 32000); \n        _dataStore.setUint(Keys.tokenTransferGasLimit(address(_marketProps1.marketToken)), 32000);  \n        _dataStore.setUint(Keys.tokenTransferGasLimit(address(_marketPropsAB.marketToken)), 32000);\n        _dataStore.setUint(Keys.tokenTransferGasLimit(address(_marketPropsBC.marketToken)), 32000);\n        _dataStore.setUint(Keys.tokenTransferGasLimit(address(_marketPropsCwnt.marketToken)), 32000);\n\n\n        /* Configure the system parameters/limits here */\n        _dataStore.setUint(Keys.MAX_CALLBACK_GAS_LIMIT, 10000);\n        _dataStore.setUint(Keys.EXECUTION_GAS_FEE_BASE_AMOUNT, 100);\n        _dataStore.setUint(Keys.MAX_ORACLE_PRICE_AGE, 2 hours);\n        _dataStore.setUint(Keys.MIN_ORACLE_BLOCK_CONFIRMATIONS, 3);\n        _dataStore.setUint(Keys.MIN_COLLATERAL_USD, 1e30);  // just require $1 as min collateral usd\n        _dataStore.setUint(Keys.reserveFactorKey(_marketProps1.marketToken, true), 5e29); // 50%\n        _dataStore.setUint(Keys.reserveFactorKey(_marketProps1.marketToken, false), 5e29);\n        _dataStore.setUint(Keys.fundingExponentFactorKey(_marketProps1.marketToken), 1.1e30); // 2 in 30 decimals like a square, cube, etc\n         _dataStore.setUint(Keys.fundingFactorKey(_marketProps1.marketToken), 0.0000001e30);\n         _dataStore.setUint(Keys.borrowingFactorKey(_marketProps1.marketToken, true), 0.87e30);\n         _dataStore.setUint(Keys.borrowingFactorKey(_marketProps1.marketToken, false), 0.96e30);\n         _dataStore.setUint(Keys.borrowingExponentFactorKey(_marketProps1.marketToken, true), 2.1e30);\n         _dataStore.setUint(Keys.borrowingExponentFactorKey(_marketProps1.marketToken, false), 2.3e30);\n         _dataStore.setUint(Keys.positionImpactExponentFactorKey(_marketProps1.marketToken), 2e30);\n         _dataStore.setUint(Keys.positionImpactFactorKey(_marketProps1.marketToken, true), 5e22); \n         _dataStore.setUint(Keys.positionImpactFactorKey(_marketProps1.marketToken, false), 1e23);\n\n        // set the limit of market tokens\n\n        _dataStore.setUint(Keys.maxPoolAmountKey(_marketProps1.marketToken, _marketProps1.longToken), 1000e18);\n        _dataStore.setUint(Keys.maxPoolAmountKey(_marketProps1.marketToken, _marketProps1.shortToken), 1000e18);\n        _dataStore.setUint(Keys.maxPoolAmountKey(_marketPropsAB.marketToken, _marketPropsAB.longToken), 1000e18);\n        _dataStore.setUint(Keys.maxPoolAmountKey(_marketPropsAB.marketToken, _marketPropsAB.shortToken), 1000e18);\n        _dataStore.setUint(Keys.maxPoolAmountKey(_marketPropsBC.marketToken, _marketPropsBC.longToken), 1000e18);\n        _dataStore.setUint(Keys.maxPoolAmountKey(_marketPropsBC.marketToken, _marketPropsBC.shortToken), 1000e18);\n        _dataStore.setUint(Keys.maxPoolAmountKey(_marketPropsCwnt.marketToken, _marketPropsCwnt.longToken), 1000e18);\n        _dataStore.setUint(Keys.maxPoolAmountKey(_marketPropsCwnt.marketToken, _marketPropsCwnt.shortToken), 1000e18);\n        \n        \n        // set max open interest for each market\n        _dataStore.setUint(Keys.maxOpenInterestKey(_marketProps1.marketToken, true), 1e39); // 1B $ \n        _dataStore.setUint(Keys.maxOpenInterestKey(_marketProps1.marketToken, false), 1e39); // 1B $\n\n        _dataStore.setUint(Keys.maxPnlFactorKey(Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS, _marketProps1.marketToken, true), 10**29); // maxPnlFactor = 10% for long\n         _dataStore.setUint(Keys.maxPnlFactorKey(Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS, _marketProps1.marketToken, false), 10**29); // maxPnlFactor = 10% for short\n        // _dataStore.setBool(Keys.cancelDepositFeatureDisabledKey(address(_depositHandler)), true);\n        _dataStore.setBool(Keys.cancelOrderFeatureDisabledKey(address(_orderHandler), uint256(Order.OrderType.MarketIncrease)), true);\n\n         addFourSigners();\n         address(_wnt).call{value: 10000e18}("");\n         depositor1 = address(0x801);\n         depositor2 = address(0x802);\n         depositor3 = address(0x803);\n\n         // make sure each depositor has some tokens.\n         _wnt.transfer(depositor1, 1000e18);\n         _wnt.transfer(depositor2, 1000e18);\n         _wnt.transfer(depositor3, 1000e18);  \n         _usdc.transfer(depositor1, 1000e18);\n         _usdc.transfer(depositor2, 1000e18);\n         _usdc.transfer(depositor3, 1000e18);\n         _tokenA.transfer(depositor1, 1000e18);\n         _tokenB.transfer(depositor1, 1000e18);\n         _tokenC.transfer(depositor1, 1000e18);   \n\n         printAllTokens();                 \n    }\n\n    error Unauthorized(string);\n   // error Error(string);\n\n\nfunction testLimit() public{\n          OracleUtils.SetPricesParams memory priceParams = createSetPricesParams();\n          \n          vm.roll(block.number+2); // block 3\n\n          \n          bytes32 key = createDepositNoSwap(_marketProps1, depositor1, 90e18, true); // create a deposit at block 3 which is within range (2, 6)          \n          _depositHandler.executeDeposit(key, priceParams);  \n          uint mintedMarketTokens = IERC20(_marketProps1.marketToken).balanceOf(depositor1);\n          key = createDepositNoSwap(_marketProps1, depositor1, 100e18, false); // create a deposit at block 3 which is within range (2, 6)          \n          _depositHandler.executeDeposit(key, priceParams);  \n          mintedMarketTokens = IERC20(_marketProps1.marketToken).balanceOf(depositor1);\n          console2.log("Experiment 1  is completed.");     \n      \n          // console2.log("PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP");\n          \n          key = createMarketSwapOrder(depositor1,  address(_wnt), 1e15); // create a deposit at block 3 which is within range (2, 6)          \n          _orderHandler.executeOrder(key, priceParams);  \n          console2.log("Experiment 2  is completed.");    \n   \n\n        console2.log("\n\n depositor 1 createMarketIncreaseOrder");\n         key = createMarketIncreaseOrder(depositor1, _marketProps1.marketToken, _marketProps1.longToken, 20e18, 1001e30, 106000000000000, true); // \n         console2.log("\nExecuting the order// rest of code");\n         _orderHandler.executeOrder(key, priceParams);\n         Position.printPosition(_dataStore, depositor1, _marketProps1.marketToken, _marketProps1.longToken, true);\n         console2.log("Experiment 3  is completed.");     \n      \n          \n\n        console2.log("\n\n depositor 2 createMarketIncreaseOrder");\n         key = createMarketIncreaseOrder(depositor2, _marketProps1.marketToken, _marketProps1.longToken, 110e18, 13e30, 101000000000000, false); // 110 usdc as collateral\n         console2.log("\nExecuting the order// rest of code");\n         _orderHandler.executeOrder(key, priceParams);\n         Position.printPosition(_dataStore, depositor2, _marketProps1.marketToken, _marketProps1.longToken, false);\n       console2.log("Experiment 4  is completed.");     \n      \n\n\n        console2.log("PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP");\n        vm.warp(2 days);\n        setIndexTokenPrice(priceParams, 98, 100); // send 20e18 USDC, increase $13.123 in a long position with trigger price 101\n        key = createLimitIncreaseOrder(depositor3, _marketProps1.marketToken, _marketProps1.shortToken, 23e18, 1.1234567e30, 101000000000000, true); // collateral token, usdsize, price\n        console2.log("a LimitIncrease order created by depositor3 with key: ");\n         console2.logBytes32(key);\n         Position.printPosition(_dataStore, depositor3, _marketProps1.marketToken, _marketProps1.shortToken, true);\n         console2.log("\n\nExecuting the order, exiting moment// rest of code\n\n");\n         _orderHandler.executeOrder(key, priceParams);\n         Position.printPosition(_dataStore, depositor3, _marketProps1.marketToken, _marketProps1.shortToken, true);\n         console2.log("Experiment  5 is completed.\n");     \n      \n\n        // depositor3 creates a LimitDecrease order\n        /*\n        setIndexTokenPrice(priceParams, 120, 125);\n        key = createLimitDecreaseOrder(depositor3, _marketProps1.marketToken, _marketProps1.shortToken, 7e18, 58e30, 120000000000000, 120000000000000, true); // retrieve $50? collateral token, usdsize, acceptible price\n        console2.log("a LimitIncrease order created by depositor3 with key: ");\n         console2.logBytes32(key);\n         Position.printPosition(_dataStore, depositor3, _marketProps1.marketToken, _marketProps1.shortToken, true);\n         console2.log("\n\nExecuting the order, exiting moment// rest of code\n\n");\n          _orderHandler.executeOrder(key, priceParams);          \n        console2.log("Experiment 7 for is completed.");     \n        */\n}\n\nfunction testMarketDecrease() public{\n    \n          OracleUtils.SetPricesParams memory priceParams = createSetPricesParams();\n          \n          vm.roll(block.number+2); // block 3\n\n          \n          bytes32 key = createDepositNoSwap(_marketProps1, depositor1, 90e18, true); // create a deposit at block 3 which is within range (2, 6)          \n          _depositHandler.executeDeposit(key, priceParams);  \n          uint mintedMarketTokens = IERC20(_marketProps1.marketToken).balanceOf(depositor1);\n          key = createDepositNoSwap(_marketProps1, depositor1, 100e18, false); // create a deposit at block 3 which is within range (2, 6)          \n          _depositHandler.executeDeposit(key, priceParams);  \n          mintedMarketTokens = IERC20(_marketProps1.marketToken).balanceOf(depositor1);\n         console2.log("Experiment 1  is completed.");     \n      \n          \n          \n        \n          console2.log("\n\n depositor 2 deposit into marketProps1");\n          key = createDepositNoSwap(_marketProps1, depositor2, 100e18, true);\n          _depositHandler.executeDeposit(key, priceParams);\n         mintedMarketTokens = IERC20(_marketProps1.marketToken).balanceOf(depositor2);\n          printPoolsAmounts();\n         console2.log("Experiment 2  is completed.");     \n      \n       \n        console2.log("\n\n depositor 1 createMarketIncreaseOrder");\n         key = createMarketIncreaseOrder(depositor1, _marketProps1.marketToken, _marketProps1.longToken, 20e18, 1e25, 106000000000000, true); // \n         console2.log("\nExecuting the order// rest of code");\n         _orderHandler.executeOrder(key, priceParams);\n         Position.printPosition(_dataStore, depositor1, _marketProps1.marketToken, _marketProps1.longToken, true);\n         console2.log("Experiment 3  is completed.");     \n      \n          \n\n        console2.log("\n\n depositor 2 createMarketIncreaseOrder");\n         key = createMarketIncreaseOrder(depositor2, _marketProps1.marketToken, _marketProps1.longToken, 110e18, 1e25, 101000000000000, false); // 110 usdc as collateral\n         console2.log("\nExecuting the order// rest of code");\n         _orderHandler.executeOrder(key, priceParams);\n         Position.printPosition(_dataStore, depositor2, _marketProps1.marketToken, _marketProps1.longToken, false);\n       console2.log("Experiment 4  is completed.");     \n      \n        console2.log("********************************************");\n\n         // deposit 2 will execute a marketDecreaseOrder now\n         key =  createMarketDecreaseOrder(depositor2, _marketProps1.marketToken, _marketProps1.longToken, 70000000000000, 5e23, false) ; // decrease by 5%\n         console2.log("a market desced order created with key: ");\n         console2.logBytes32(key);\n         console2.log("\nExecuting the order// rest of code");         \n         setIndexTokenPrice(priceParams, 60, 65); // we have a profit for a short position\n         _orderHandler.executeOrder(key, priceParams);\n         Position.printPosition(_dataStore, depositor2, _marketProps1.marketToken, _marketProps1.longToken, false);\n         console2.log("Experiment 5  is completed.");  \n\n          printAllTokens();\n}   \n\n   \n\nfunction  testLiquidation() public{\n          // blockrange (2, 6)\n          OracleUtils.SetPricesParams memory priceParams = createSetPricesParams();\n          \n          vm.roll(block.number+2); // block 3\n\n          \n          bytes32 key = createDepositNoSwap(_marketProps1, depositor1, 90e18, true); // create a deposit at block 3 which is within range (2, 6)          \n          _depositHandler.executeDeposit(key, priceParams);  \n          uint mintedMarketTokens = IERC20(_marketProps1.marketToken).balanceOf(depositor1);\n          key = createDepositNoSwap(_marketProps1, depositor1, 100e18, false); // create a deposit at block 3 which is within range (2, 6)          \n          _depositHandler.executeDeposit(key, priceParams);  \n          mintedMarketTokens = IERC20(_marketProps1.marketToken).balanceOf(depositor1);\n         console2.log("Experiment 1  is completed.");     \n      \n          \n          \n        \n          console2.log("\n\n depositor 2 deposit into marketProps1");\n          key = createDepositNoSwap(_marketProps1, depositor2, 100e18, true);\n          _depositHandler.executeDeposit(key, priceParams);\n         mintedMarketTokens = IERC20(_marketProps1.marketToken).balanceOf(depositor2);\n          printPoolsAmounts();\n         console2.log("Experiment 2  is completed.");     \n      \n       \n        console2.log("\n\n depositor 1 createMarketIncreaseOrder");\n         key = createMarketIncreaseOrder(depositor1, _marketProps1.marketToken, _marketProps1.longToken, 10e18, 1e25, 106000000000000, true);\n         console2.log("\nExecuting the order// rest of code");\n         _orderHandler.executeOrder(key, priceParams);\n         Position.printPosition(_dataStore, depositor1, _marketProps1.marketToken, _marketProps1.longToken, true);\n         console2.log("Experiment 3  is completed.");     \n      \n          \n\n        console2.log("\n\n depositor 2 createMarketIncreaseOrder");\n         key = createMarketIncreaseOrder(depositor2, _marketProps1.marketToken, _marketProps1.shortToken, 100e18, 1e25, 101000000000000, false);\n         console2.log("\nExecuting the order// rest of code");\n         _orderHandler.executeOrder(key, priceParams);\n         Position.printPosition(_dataStore, depositor2, _marketProps1.marketToken, _marketProps1.shortToken, false);\n       console2.log("Experiment 4  is completed.");     \n      \n          \n\n         // deposit 2 will execute a marketDecreaseOrder now\n         key =  createMarketDecreaseOrder(depositor2, _marketProps1.marketToken, _marketProps1.shortToken, 106000000000000, 5e23, false) ; // decrease by 5%\n         console2.log("a market desced order created with key: ");\n         console2.logBytes32(key);\n         console2.log("\nExecuting the order// rest of code");         \n         setIndexTokenPrice(priceParams, 84, 90);\n         _orderHandler.executeOrder(key, priceParams);\n         Position.printPosition(_dataStore, depositor2, _marketProps1.marketToken, _marketProps1.shortToken, false);\n         console2.log("Experiment 5  is completed.");     \n      \n          \n\n        \n        // depositor3 will execute a LimitIncrease Order now\n        key = createMarketIncreaseOrder(depositor3, _marketProps1.marketToken, _marketProps1.shortToken, 20e18, 200e30, 101000000000000, true); // collateral token, usdsize, price\n        console2.log("a LimitIncrease order created by depositor3 with key: ");\n         console2.logBytes32(key);\n         Position.printPosition(_dataStore, depositor3, _marketProps1.marketToken, _marketProps1.shortToken, true);\n         console2.log("\n\nExecuting the order, exiting moment// rest of code\n\n");\n         _orderHandler.executeOrder(key, priceParams);\n         Position.printPosition(_dataStore, depositor3, _marketProps1.marketToken, _marketProps1.shortToken, true);\n         console2.log("Experiment  6 is completed.\n");     \n      \n\n        // depositor3 creates a LimitDecrease order\n        setIndexTokenPrice(priceParams, 120, 125);\n        key = createLimitDecreaseOrder(depositor3, _marketProps1.marketToken, _marketProps1.shortToken, 7e18, 58e30, 120000000000000, 120000000000000, true); // retrieve $50? collateral token, usdsize, acceptible price\n        console2.log("a LimitIncrease order created by depositor3 with key: ");\n         console2.logBytes32(key);\n         Position.printPosition(_dataStore, depositor3, _marketProps1.marketToken, _marketProps1.shortToken, true);\n         console2.log("\n\nExecuting the order, exiting moment// rest of code\n\n");\n          _orderHandler.executeOrder(key, priceParams);          \n        console2.log("Experiment 7 for is completed.");     \n      \n        // depositor3 creates a stopLossDecrease order\n        setIndexTokenPrice(priceParams, 97, 99);\n        key = createStopLossDecrease(depositor3, _marketProps1.marketToken, _marketProps1.shortToken, 7e18, 58e30, 95000000000000, 92000000000000, true); // retrieve $50? collateral token, usdsize, acceptible price\n        console2.log("a StopLossDecrease order created by depositor3 with key: ");\n         console2.logBytes32(key);\n         // Position.printPosition(_dataStore, depositor3, _marketProps1.marketToken, _marketProps1.shortToken, true);\n\n        console2.log("\n\nExecuting the order, exiting moment// rest of code\n\n");\n        _orderHandler.executeOrder(key, priceParams);\n        console2.log("Experiment 8 is completed.");     \n      \n        \n         console2.log("\n\n*************************************************\n\n");\n\n\n        // depositor3 creates a Liquidation order\n        setIndexTokenPrice(priceParams, 75, 75);\n        console2.log("Liquidate a position// rest of code");\n        Position.printPosition(_dataStore, depositor3, _marketProps1.marketToken, _marketProps1.shortToken, true);\n        _liquidationHandler.executeLiquidation(depositor3, _marketProps1.marketToken, _marketProps1.shortToken, true, priceParams);\n        console2.log("Experiment 9 is completed.");     \n      \n\n         // printPoolsAmounts();\n         printAllTokens();\n\n             \n      \n         \n}\n\nfunction printAllTokens() startedCompleted("printAllTokens") public\n{\n      console2.log("\nTokens used in this test:");\n        console2.log("_wnt: "); console2.logAddress(address(_wnt));\n        console2.log("_usdc: "); console2.logAddress(address(_usdc));\n        console2.log("_sol: "); console2.logAddress(address(_sol));\n        console2.log("_tokenA: "); console2.logAddress(address(_tokenA));\n        console2.log("_tokenB: "); console2.logAddress(address(_tokenB));\n        console2.log("_tokenC: "); console2.logAddress(address(_tokenC));\n        console2.logString("test contract address:"); console2.logAddress(address(this));\n        \n        console2.log("_marketProps1 market token: "); console2.logAddress(address(_marketProps1.marketToken));\n        console2.log("_marketPropsAB market token: "); console2.logAddress(address(_marketPropsAB.marketToken));\n        console2.log("_marketPropsBC market token: "); console2.logAddress(address(_marketPropsBC.marketToken));\n        console2.log("_marketProps1Cwnt market token: "); console2.logAddress(address(_marketPropsCwnt.marketToken));\n        console2.log("\n");\n        \n        \n}\n\n\nfunction printMarketTokenAmount() public \n{   console2.log("Market token address: ");\n    console2.logAddress(address(_marketProps1.marketToken));\n    console2.log("depositor1 market token amount: %d", IERC20(_marketProps1.marketToken).balanceOf(depositor1));\n    console2.log("depositor2 market token amount: %d", IERC20(_marketProps1.marketToken).balanceOf(depositor2));\n    console2.log("depositor3 market token amount: %d", IERC20(_marketProps1.marketToken).balanceOf(depositor3));\n}\n\nfunction printLongShortTokens(address account) public\n{\n    console2.log("balance for "); console2.logAddress(account);\n    console2.log("_wnt balance:", _wnt.balanceOf(account));\n    console2.log("usdc balance:", _usdc.balanceOf(account));\n}\n\n\n\n\nfunction addFourSigners() private {\n    _oracleStore.addSigner(address(901));\n    _oracleStore.addSigner(address(902));    \n    _oracleStore.addSigner(address(903));   \n    _oracleStore.addSigner(address(904));   \n}\n\n\nfunction setIndexTokenPrice(OracleUtils.SetPricesParams memory priceParams, uint256 minP, uint256 maxP) public\n{\n    uint256 mask1 = ~uint256(type(uint96).max);   // (32*3 of 1's)\n    console2.logBytes32(bytes32(mask1));\n\n    uint256 minPrice = minP;\n    minPrice = minPrice << 32 | minP;\n    minPrice = minPrice << 32 | minP;\n\n    uint256 maxPrice = maxP;\n    maxPrice = maxPrice << 32 | maxP;\n    maxPrice = maxPrice << 32 | maxP;\n\n    priceParams.compactedMinPrices[0] = (priceParams.compactedMinPrices[0] & mask1) | minPrice;\n    priceParams.compactedMaxPrices[0] = (priceParams.compactedMaxPrices[0] & mask1) | maxPrice;\n}\n\n\nfunction createSetPricesParams() public returns (OracleUtils.SetPricesParams memory) {\n          uint256 signerInfo = 3;    // signer 904\n          signerInfo = signerInfo << 16 | 2; // signer 903\n          signerInfo = signerInfo << 16 | 1; // signer 902\n          signerInfo = signerInfo << 16 | 3; // number of singers\n          // will read out as 902, 903, 904 from the lowest first\n\n          // the number of tokens, 6\n          address[] memory tokens = new address[](6);\n          tokens[0] = address(_sol);\n          tokens[1] = address(_wnt);\n          tokens[2] = address(_usdc);\n          tokens[3] = address(_tokenA);\n          tokens[4] = address(_tokenB);\n          tokens[5] = address(_tokenC);\n\n         // must be equal to the number of tokens 6, 64 for each one, so 64*6. 64*4 for one element, so need two elements \n          uint256[] memory compactedMinOracleBlockNumbers = new uint256[](2);\n          compactedMinOracleBlockNumbers[0] = block.number+1;\n          compactedMinOracleBlockNumbers[0] = compactedMinOracleBlockNumbers[0] << 64 | block.number+1;\n          compactedMinOracleBlockNumbers[0] = compactedMinOracleBlockNumbers[0] << 64 | block.number+1;\n          compactedMinOracleBlockNumbers[0] = compactedMinOracleBlockNumbers[0] << 64 | block.number+1;\n\n          compactedMinOracleBlockNumbers[1] = block.number+1;\n          compactedMinOracleBlockNumbers[1] = compactedMinOracleBlockNumbers[0] << 64 | block.number+1;\n          \n        // must be equal to the number of tokens 6, 64 for each one, so 64*6. 64*4 for one element, so need two elements \n         \n          uint256[] memory compactedMaxOracleBlockNumbers = new uint256[](2);\n          compactedMaxOracleBlockNumbers[0] = block.number+5; \n          compactedMaxOracleBlockNumbers[0] = compactedMaxOracleBlockNumbers[0] << 64 | block.number+5;\n          compactedMaxOracleBlockNumbers[0] = compactedMaxOracleBlockNumbers[0] << 64 | block.number+5;  \n          compactedMaxOracleBlockNumbers[0] = compactedMaxOracleBlockNumbers[0] << 64 | block.number+5;  \n\n          compactedMaxOracleBlockNumbers[1] = block.number+5; \n          compactedMaxOracleBlockNumbers[1] = compactedMaxOracleBlockNumbers[0] << 64 | block.number+5;\n\n         // must be equal to the number of tokens 6, 64 for each one, so 64*6. 64*4 for one element, so need two elements \n          uint256[] memory compactedOracleTimestamps = new uint256[](2);\n          compactedOracleTimestamps[0]  =  9;\n          compactedOracleTimestamps[0] = compactedOracleTimestamps[0] << 64 | 8;\n          compactedOracleTimestamps[0] = compactedOracleTimestamps[0] << 64 | 7;\n          compactedOracleTimestamps[0] = compactedOracleTimestamps[0] << 64 | 7;\n          \n          compactedOracleTimestamps[1]  =  9;\n          compactedOracleTimestamps[1] = compactedOracleTimestamps[0] << 64 | 8;\n          \n\n           // must be equal to the number of tokens, 8 for each, so 8*6= 48, only need one element\n           uint256[] memory compactedDecimals = new uint256[](1);\n           compactedDecimals[0] =  12;\n           compactedDecimals[0] =  compactedDecimals[0] << 8 | 12;\n           compactedDecimals[0] =  compactedDecimals[0] << 8 | 12;\n           compactedDecimals[0] =  compactedDecimals[0] << 8 | 12;\n           compactedDecimals[0] =  compactedDecimals[0] << 8 | 12;\n           compactedDecimals[0] =  compactedDecimals[0] << 8 | 12;\n           \n           \n           // three signers, 6 tokens, so we have 3*6 = 18 entries, each entry takes 32 bits, so each 8 entries takes one element, we need 3 elements\n           // price table:\n           //      SOL:        100 101 102\n           //      wnt:        200 201 203\n           //      USDC        1   1    1\n           //      tokenA      100 101  102\n           //      tokenB      200 202  204\n           //      tokenC      400 404  408\n\n           uint256[] memory compactedMinPrices = new uint256[](3);\n           compactedMinPrices[2] = 408;        \n           compactedMinPrices[2] = compactedMinPrices[2] << 32 | 404;\n\n           compactedMinPrices[1] = 400;\n           compactedMinPrices[1] = compactedMinPrices[1] << 32 | 204;\n           compactedMinPrices[1] = compactedMinPrices[1] << 32 | 202;\n           compactedMinPrices[1] = compactedMinPrices[1] << 32 | 200;\n           compactedMinPrices[1] = compactedMinPrices[1] << 32 | 102;\n           compactedMinPrices[1] = compactedMinPrices[1] << 32 | 101;\n           compactedMinPrices[1] = compactedMinPrices[1] << 32 | 100;\n           compactedMinPrices[1] = compactedMinPrices[1] << 32 | 1;\n           \n           compactedMinPrices[0] = 1;\n           compactedMinPrices[0] = compactedMinPrices[0] << 32 | 1;\n           compactedMinPrices[0] = compactedMinPrices[0] << 32 | 203;\n           compactedMinPrices[0] = compactedMinPrices[0] << 32 | 201;\n           compactedMinPrices[0] = compactedMinPrices[0] << 32 | 200;\n           compactedMinPrices[0] = compactedMinPrices[0] << 32 | 102;\n           compactedMinPrices[0] = compactedMinPrices[0] << 32 | 101;\n           compactedMinPrices[0] = compactedMinPrices[0] << 32 | 100;\n           \n           // three signers, 6 tokens, so we have 3*6 = 18 entries, each entry takes 8 bits, so we just need one element\n\n           uint256[] memory compactedMinPricesIndexes = new uint256[](1);\n           compactedMinPricesIndexes[0] = 1;\n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 2;\n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 0;\n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 1;\n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 2;\n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 0;\n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 1;\n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 2;\n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 0;    \n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 1;\n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 2;\n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 0;    \n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 1;\n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 2;\n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 0;    \n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 1;\n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 2;\n           compactedMinPricesIndexes[0] = compactedMinPricesIndexes[0] << 8 | 0;    \n           \n           // three signers, 6 tokens, so we have 3*6 = 18 entries, each entry takes 32 bits, so each 8 entries takes one element, we need 3 elements\n           // price table:\n           //      SOL:        105 106 107\n           //      wnt:        205 206 208\n           //      USDC        1   1    1\n           //      tokenA      105 106  107\n           //      tokenB      205 207  209\n           //      tokenC      405 409  413\n           uint256[] memory compactedMaxPrices = new uint256[](3);\n           compactedMaxPrices[2] = 413;\n           compactedMaxPrices[2] = compactedMaxPrices[2] << 32 | 409;\n           \n           compactedMaxPrices[1] = 405;\n           compactedMaxPrices[1] = compactedMaxPrices[1] << 32 | 209;\n           compactedMaxPrices[1] = compactedMaxPrices[1] << 32 | 207;\n           compactedMaxPrices[1] = compactedMaxPrices[1] << 32 | 205;\n           compactedMaxPrices[1] = compactedMaxPrices[1] << 32 | 107;\n           compactedMaxPrices[1] = compactedMaxPrices[1] << 32 | 106;\n           compactedMaxPrices[1] = compactedMaxPrices[1] << 32 | 105;\n           compactedMaxPrices[1] = compactedMaxPrices[1] << 32 | 1;\n\n           compactedMaxPrices[0] = 1;\n           compactedMaxPrices[0] = compactedMaxPrices[0] << 32 | 1;\n           compactedMaxPrices[0] = compactedMaxPrices[0] << 32 | 208;\n           compactedMaxPrices[0] = compactedMaxPrices[0] << 32 | 206; \n           compactedMaxPrices[0] = compactedMaxPrices[0] << 32 | 205; \n           compactedMaxPrices[0] = compactedMaxPrices[0] << 32 | 107;\n           compactedMaxPrices[0] = compactedMaxPrices[0] << 32 | 106;\n           compactedMaxPrices[0] = compactedMaxPrices[0] << 32 | 105;\n            \n           \n            // three signers, 6 tokens, so we have 3*6 = 18 entries, each entry takes 8 bits, so we just need one element\n\n            uint256[] memory compactedMaxPricesIndexes = new uint256[](1);\n            compactedMaxPricesIndexes[0] = 1; \n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 2;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 0;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 1;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 2;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 0;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 1;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 2;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 0;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 1;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 2;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 0;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 1;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 2;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 0;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 1;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 2;\n            compactedMaxPricesIndexes[0] = compactedMaxPricesIndexes[0] << 8 | 0;\n            \n           // 3 signers and 6 tokens, so we need 3*6 signatures\n            bytes[] memory signatures = new bytes[](18);\n            for(uint i; i<18; i++){\n                signatures[i] = abi.encode("SIGNATURE");\n            }\n            address[] memory priceFeedTokens;\n\n          OracleUtils.SetPricesParams memory priceParams = OracleUtils.SetPricesParams(\n               signerInfo,\n               tokens,\n               compactedMinOracleBlockNumbers,\n               compactedMaxOracleBlockNumbers,\n               compactedOracleTimestamps,\n               compactedDecimals,\n               compactedMinPrices, \n               compactedMinPricesIndexes,\n               compactedMaxPrices, \n               compactedMaxPricesIndexes, \n               signatures, \n               priceFeedTokens\n          );\n          return priceParams;\n}\n\n/* \n*  The current index token price (85, 90), a trader sets a trigger price to 100 and then acceptabiel price to 95.\n*  He like to long the index token. \n*  1. Pick the primary price 90 since we long, so choose the max\n*  2. Make sure 90 < 100, and pick (90, 100) as the custom price since we long\n*  3. Choose price 95 since 95 is within the range, and it is the highest acceptible price. Choosing 90 \n*      will be in favor of the trader\n* \n*/\n\nfunction createMarketSwapOrder(address account,  address inputToken, uint256 inAmount) public returns(bytes32)\n{   \n    address[] memory swapPath = new address[](1);\n    swapPath[0] =  _marketProps1.marketToken;\n    // swapPath[0] = _marketPropsAB.marketToken;\n    // swapPath[1] = _marketPropsBC.marketToken;\n    // swapPath[2] = _marketPropsCwnt.marketToken;\n\n    \n    vm.prank(account);    \n    _wnt.transfer(address(_orderVault), 3200);  // execution fee\n\n\n    BaseOrderUtils.CreateOrderParams memory params;\n    params.addresses.receiver = account;            // the account is the receiver\n    params.addresses.callbackContract = address(0);\n    params.addresses.uiFeeReceiver = account;   // set myself as the ui receiver\n    // params.addresses.market = marketToken;\n    params.addresses.initialCollateralToken = inputToken; // initial token\n    params.addresses.swapPath = swapPath;\n\n    // params.numbers.sizeDeltaUsd = sizeDeltaUsd;\n    params.numbers.initialCollateralDeltaAmount = inAmount ; // this is actually useless, will be overidden by real transfer amount\n     vm.prank(account);    \n    IERC20(inputToken).transfer(address(_orderVault), inAmount);  // this is the real amount\n\n\n    // params.numbers.triggerPrice = triggerPrice;\n    // params.numbers.acceptablePrice = acceptablePrice; // I can buy with this price or lower effective spread control \n    params.numbers.executionFee = 3200;\n    params.numbers.callbackGasLimit = 3200;\n   // params.numbers.initialCollateralDeltaAmount = inAmount;\n    params.numbers.minOutputAmount = 100; // use the control the final collateral amount, not for the position size delta, which is indirectly controlled by acceptable price\n\n    params.orderType = Order.OrderType.MarketSwap;\n    params.decreasePositionSwapType = Order.DecreasePositionSwapType.NoSwap;\n    // params.isLong = isLong;\n    params.shouldUnwrapNativeToken = false;\n    params.referralCode = keccak256(abi.encode("MY REFERRAL"));\n\n    vm.prank(account);\n    bytes32 key = _erouter.createOrder(params);\n    return key;\n}\n\n\n\nfunction createLiquidationOrder(address account, address marketToken, address collateralToken, uint256 collateralAmount, uint sizeDeltaUsd, uint triggerPrice, uint256 acceptablePrice, bool isLong) public returns(bytes32)\n{\n    address[] memory swapPath;\n    \n    //address[] memory swapPath = new address[](3);\n    //swapPath[0] = _marketPropsAB.marketToken;\n    //swapPath[1] = _marketPropsBC.marketToken;\n    //swapPath[2] = _marketPropsCwnt.marketToken;\n\n    \n    vm.prank(account);    \n    _wnt.transfer(address(_orderVault), 3200);  // execution fee\n\n\n    BaseOrderUtils.CreateOrderParams memory params;\n    params.addresses.receiver = account;\n    params.addresses.callbackContract = address(0);\n    params.addresses.uiFeeReceiver = uiFeeReceiver;\n    params.addresses.market = marketToken; // final market\n    params.addresses.initialCollateralToken = collateralToken; // initial token\n    params.addresses.swapPath = swapPath;\n\n    params.numbers.sizeDeltaUsd = sizeDeltaUsd;\n    // params.numbers.initialCollateralDeltaAmount = ; // this is actually useless, will be overidden by real transfer amount\n     vm.prank(account);    \n    IERC20(collateralToken).transfer(address(_orderVault), collateralAmount);  // this is the real amount\n\n\n    params.numbers.triggerPrice = triggerPrice;\n    params.numbers.acceptablePrice = acceptablePrice; // I can buy with this price or lower effective spread control \n    params.numbers.executionFee = 3200;\n    params.numbers.callbackGasLimit = 3200;\n    params.numbers.minOutputAmount = 100; // use the control the final collateral amount, not for the position size delta, which is indirectly controlled by acceptable price\n\n    params.orderType = Order.OrderType.Liquidation;\n    params.decreasePositionSwapType = Order.DecreasePositionSwapType.NoSwap;\n    params.isLong = isLong;\n    params.shouldUnwrapNativeToken = false;\n    params.referralCode = keccak256(abi.encode("MY REFERRAL"));\n\n    vm.prank(account);\n    bytes32 key = _erouter.createOrder(params);\n    return key;\n}    \n\n\n\nfunction createStopLossDecrease(address account, address marketToken, address collateralToken, uint256 collateralAmount, uint sizeDeltaUsd, uint triggerPrice, uint256 acceptablePrice, bool isLong) public returns(bytes32)\n{\n    address[] memory swapPath;\n    \n    //address[] memory swapPath = new address[](3);\n    //swapPath[0] = _marketPropsAB.marketToken;\n    //swapPath[1] = _marketPropsBC.marketToken;\n    //swapPath[2] = _marketPropsCwnt.marketToken;\n\n    \n    vm.prank(account);    \n    _wnt.transfer(address(_orderVault), 3200);  // execution fee\n\n\n    BaseOrderUtils.CreateOrderParams memory params;\n    params.addresses.receiver = account;\n    params.addresses.callbackContract = address(0);\n    params.addresses.uiFeeReceiver = uiFeeReceiver;\n    params.addresses.market = marketToken; // final market\n    params.addresses.initialCollateralToken = collateralToken; // initial token\n    params.addresses.swapPath = swapPath;\n\n    params.numbers.sizeDeltaUsd = sizeDeltaUsd;\n    // params.numbers.initialCollateralDeltaAmount = ; // this is actually useless, will be overidden by real transfer amount\n     vm.prank(account);    \n    IERC20(collateralToken).transfer(address(_orderVault), collateralAmount);  // this is the real amount\n\n\n    params.numbers.triggerPrice = triggerPrice;\n    params.numbers.acceptablePrice = acceptablePrice; // I can buy with this price or lower effective spread control \n    params.numbers.executionFee = 3200;\n    params.numbers.callbackGasLimit = 3200;\n    params.numbers.minOutputAmount = 100; // use the control the final collateral amount, not for the position size delta, which is indirectly controlled by acceptable price\n\n    params.orderType = Order.OrderType.StopLossDecrease;\n    params.decreasePositionSwapType = Order.DecreasePositionSwapType.NoSwap;\n    params.isLong = isLong;\n    params.shouldUnwrapNativeToken = false;\n    params.referralCode = keccak256(abi.encode("MY REFERRAL"));\n\n    vm.prank(account);\n    bytes32 key = _erouter.createOrder(params);\n    return key;\n}    \n\n\n\nfunction createLimitDecreaseOrder(address account, address marketToken, address collateralToken, uint256 collateralAmount, uint sizeDeltaUsd, uint triggerPrice, uint256 acceptablePrice, bool isLong) public returns(bytes32)\n{\n    address[] memory swapPath;\n    \n    //address[] memory swapPath = new address[](3);\n    //swapPath[0] = _marketPropsAB.marketToken;\n    //swapPath[1] = _marketPropsBC.marketToken;\n    //swapPath[2] = _marketPropsCwnt.marketToken;\n\n    \n    vm.prank(account);    \n    _wnt.transfer(address(_orderVault), 3200);  // execution fee\n\n\n    BaseOrderUtils.CreateOrderParams memory params;\n    params.addresses.receiver = account;\n    params.addresses.callbackContract = address(0);\n    params.addresses.uiFeeReceiver = uiFeeReceiver;\n    params.addresses.market = marketToken; // final market\n    params.addresses.initialCollateralToken = collateralToken; // initial token\n    params.addresses.swapPath = swapPath;\n\n    params.numbers.sizeDeltaUsd = sizeDeltaUsd;\n    // params.numbers.initialCollateralDeltaAmount = ; // this is actually useless, will be overidden by real transfer amount\n     vm.prank(account);    \n    IERC20(collateralToken).transfer(address(_orderVault), collateralAmount);  // this is the real amount\n\n\n    params.numbers.triggerPrice = triggerPrice;\n    params.numbers.acceptablePrice = acceptablePrice; // I can buy with this price or lower effective spread control \n    params.numbers.executionFee = 3200;\n    params.numbers.callbackGasLimit = 3200;\n    params.numbers.minOutputAmount = 100; // use the control the final collateral amount, not for the position size delta, which is indirectly controlled by acceptable price\n\n    params.orderType = Order.OrderType.LimitDecrease;\n    params.decreasePositionSwapType = Order.DecreasePositionSwapType.NoSwap;\n    params.isLong = isLong;\n    params.shouldUnwrapNativeToken = false;\n    params.referralCode = keccak256(abi.encode("MY REFERRAL"));\n\n    vm.prank(account);\n    bytes32 key = _erouter.createOrder(params);\n    return key;\n}    \n\n\nfunction createLimitIncreaseOrder(address account, address marketToken, address collateralToken, uint256 collateralAmount, uint sizeDeltaUsd, uint triggerPrice, bool isLong) public returns(bytes32)\n{\n    address[] memory swapPath;\n    \n    //address[] memory swapPath = new address[](3);\n    //swapPath[0] = _marketPropsAB.marketToken;\n    //swapPath[1] = _marketPropsBC.marketToken;\n    //swapPath[2] = _marketPropsCwnt.marketToken;\n\n    \n    vm.prank(account);    \n    _wnt.transfer(address(_orderVault), 3200);  // execution fee\n\n\n    BaseOrderUtils.CreateOrderParams memory params;\n    params.addresses.receiver = account;\n    params.addresses.callbackContract = address(0);\n    params.addresses.uiFeeReceiver = uiFeeReceiver;\n    params.addresses.market = marketToken; // final market\n    params.addresses.initialCollateralToken = collateralToken; // initial token\n    params.addresses.swapPath = swapPath;\n\n    params.numbers.sizeDeltaUsd = sizeDeltaUsd;\n    // params.numbers.initialCollateralDeltaAmount = ; // this is actually useless, will be overidden by real transfer amount\n     vm.prank(account);    \n    IERC20(collateralToken).transfer(address(_orderVault), collateralAmount);  // this is the real amount\n\n\n    params.numbers.triggerPrice = triggerPrice;   // used for limit order\n    params.numbers.acceptablePrice = 121000000000000; // I can buy with this price or lower effective spread control \n    params.numbers.executionFee = 3200;\n    params.numbers.callbackGasLimit = 3200;\n    params.numbers.minOutputAmount = 100; // use the control the final collateral amount, not for the position size delta, which is indirectly controlled by acceptable price\n\n    params.orderType = Order.OrderType.LimitIncrease;\n    params.decreasePositionSwapType = Order.DecreasePositionSwapType.NoSwap;\n    params.isLong = isLong;\n    params.shouldUnwrapNativeToken = false;\n    params.referralCode = keccak256(abi.encode("MY REFERRAL"));\n\n    vm.prank(account);\n    bytes32 key = _erouter.createOrder(params);\n    return key;\n}    \n\n\n\n\nfunction createMarketDecreaseOrder(address account, address marketToken, address collateralToken,  uint256 acceptablePrice, uint256 sizeInUsd, bool isLong) public returns(bytes32)\n{\n    address[] memory swapPath;\n    \n    //address[] memory swapPath = new address[](3);\n    //swapPath[0] = _marketPropsAB.marketToken;\n    //swapPath[1] = _marketPropsBC.marketToken;\n    //swapPath[2] = _marketPropsCwnt.marketToken;\n\n    \n    vm.prank(account);    \n    _wnt.transfer(address(_orderVault), 3200);  // execution fee\n\n\n    BaseOrderUtils.CreateOrderParams memory params;\n    params.addresses.receiver = account;\n    params.addresses.callbackContract = address(0);\n    params.addresses.uiFeeReceiver = uiFeeReceiver;\n    params.addresses.market = marketToken; // final market\n    params.addresses.initialCollateralToken = collateralToken; // initial token\n    params.addresses.swapPath = swapPath;\n\n    params.numbers.sizeDeltaUsd = sizeInUsd; // how much dollar to decrease, will convert into amt of tokens to decrease in long/short based on the execution price\n    params.numbers.initialCollateralDeltaAmount = 13e18; // this is actually useless, will be overidden by real transfer amount\n    // vm.prank(account);    \n    // IERC20(collateralToken).transfer(address(_orderVault), collateralAmount);  // this is the real amount\n\n\n    params.numbers.triggerPrice = 0;\n    params.numbers.acceptablePrice = acceptablePrice; // I can buy with this price or lower effective spread control \n    params.numbers.executionFee = 3200;\n    params.numbers.callbackGasLimit = 3200;\n    params.numbers.minOutputAmount = 10e18; // use the control the final collateral amount, not for the position size delta, which is indirectly controlled by acceptable price\n\n    params.orderType = Order.OrderType.MarketDecrease;\n    params.decreasePositionSwapType = Order.DecreasePositionSwapType.NoSwap;\n    params.isLong = isLong;\n    params.shouldUnwrapNativeToken = false;\n    params.referralCode = keccak256(abi.encode("MY REFERRAL"));\n\n    vm.prank(account);\n    bytes32 key = _erouter.createOrder(params);\n    return key;\n}    \n\n\n\nfunction createMarketIncreaseOrder(address account, address marketToken, address collateralToken, uint256 collateralAmount, uint sizeDeltaUsd, uint acceptablePrice, bool isLong) public returns(bytes32)\n{\n    address[] memory swapPath;\n    \n    //address[] memory swapPath = new address[](3);\n    //swapPath[0] = _marketPropsAB.marketToken;\n    //swapPath[1] = _marketPropsBC.marketToken;\n    //swapPath[2] = _marketPropsCwnt.marketToken;\n\n    \n    vm.prank(account);    \n    _wnt.transfer(address(_orderVault), 3200);  // execution fee\n\n\n    BaseOrderUtils.CreateOrderParams memory params;\n    params.addresses.receiver = account;\n    params.addresses.callbackContract = address(0);\n    params.addresses.uiFeeReceiver = uiFeeReceiver;\n    params.addresses.market = marketToken; // final market\n    params.addresses.initialCollateralToken = collateralToken; // initial token\n    params.addresses.swapPath = swapPath;\n\n    params.numbers.sizeDeltaUsd = sizeDeltaUsd;\n    // params.numbers.initialCollateralDeltaAmount = ; // this is actually useless, will be overidden by real transfer amount\n     vm.prank(account);    \n    IERC20(collateralToken).transfer(address(_orderVault), collateralAmount);  // this is the real amount\n\n\n    params.numbers.triggerPrice = 0;\n    params.numbers.acceptablePrice = acceptablePrice; // I can buy with this price or lower effective spread control \n    params.numbers.executionFee = 3200;\n    params.numbers.callbackGasLimit = 3200;\n    params.numbers.minOutputAmount = 100; // use the control the final collateral amount, not for the position size delta, which is indirectly controlled by acceptable price\n\n    params.orderType = Order.OrderType.MarketIncrease;\n    params.decreasePositionSwapType = Order.DecreasePositionSwapType.NoSwap;\n    params.isLong = isLong;\n    params.shouldUnwrapNativeToken = false;\n    params.referralCode = keccak256(abi.encode("MY REFERRAL"));\n\n    vm.prank(account);\n    bytes32 key = _erouter.createOrder(params);\n    return key;\n}    \n\n\n\nfunction createWithdraw(address withdrawor, uint marketTokenAmount) public returns (bytes32)\n{\n    address[] memory longTokenSwapPath;\n    address[] memory shortTokenSwapPath;\n\n    console.log("createWithdraw with withdrawor: ");\n    console.logAddress(withdrawor);\n     vm.prank(withdrawor);    \n    _wnt.transfer(address(_withdrawalVault), 3200);  // execution fee\n\n    vm.prank(withdrawor);\n    ERC20(_marketProps1.marketToken).transfer(address(_withdrawalVault), marketTokenAmount);\n\n    WithdrawalUtils.CreateWithdrawalParams memory params = WithdrawalUtils.CreateWithdrawalParams(\n        withdrawor, // receiver\n        address(0), // call back function\n        uiFeeReceiver, // uiFeeReceiver\n        _marketProps1.marketToken, // which market token to withdraw\n        longTokenSwapPath,\n        shortTokenSwapPath,\n        123, // minLongTokenAmount\n        134, // minShortTokenAmount\n        false, // shouldUnwrapNativeToken\n        3200, // execution fee\n        3200 // callback gas limit\n    );\n\n    vm.prank(withdrawor);\n    bytes32 key =   _erouter.createWithdrawal(params);\n    return key;\n}\n\n\nfunction createDepositNoSwap(Market.Props memory marketProps, address depositor, uint amount, bool isLong) public returns (bytes32){\n    address[] memory longTokenSwapPath;\n    address[] memory shortTokenSwapPath;\n\n    console.log("createDeposit with depositor: ");\n    console.logAddress(depositor);\n\n     vm.prank(depositor);\n    _wnt.transfer(address(_depositVault), 3200);  // execution fee\n    if(isLong){\n            console2.log("000000000000000000");\n           vm.prank(depositor);\n           IERC20(marketProps.longToken).transfer(address(_depositVault), amount);   \n           console2.log("bbbbbbbbbbbbbbbbbbbbbb");\n    }\n    else   {\n        console2.log("111111111111111111111111");\n        console2.log("deposit balance: %d, %d", IERC20(marketProps.shortToken).balanceOf(depositor), amount);\n           vm.prank(depositor);\n           IERC20(marketProps.shortToken).transfer(address(_depositVault), amount);\n           console2.log("qqqqqqqqqqqqqqqqqq");\n    }\n           \n\n    DepositUtils.CreateDepositParams memory params = DepositUtils.CreateDepositParams(\n        depositor,\n        address(0),\n        uiFeeReceiver,\n        marketProps.marketToken,\n        marketProps.longToken,\n        marketProps.shortToken,\n        longTokenSwapPath,\n        shortTokenSwapPath,\n        100000, // minMarketTokens\n        true,\n        3200,  // execution fee\n        3200     // call back gas limit\n    );\n\n    console2.log("aaaaaaaaaaaaaaaaaaaaaaaaa");\n    vm.prank(depositor);\n    bytes32 key1 = _erouter.createDeposit(params);\n\n    return key1;\n}\n\n/*\nfunction testCancelDeposit() public \n{\n    address[] memory longTokenSwapPath;\n    address[] memory shortTokenSwapPath;\n\n    address(_wnt).call{value: 100e8}("");\n    _wnt.transfer(address(_depositVault), 1e6);\n    DepositUtils.CreateDepositParams memory params = DepositUtils.CreateDepositParams(\n        msg.sender,\n        address(0),\n        address(111),\n        _marketProps1.marketToken,\n        _marketProps1.longToken,\n        _marketProps1.shortToken,\n        longTokenSwapPath,\n        shortTokenSwapPath,\n        100000, // minMarketTokens\n        true,\n        3200,  // execution fee\n        3200     // call back gas limit\n    );\n\n    bytes32 key1 = _erouter.createDeposit(params);\n\n    console.log("WNT balance of address(222) before cancelllation: %s", _wnt.balanceOf(address(222)));\n    console.log("WNT balance of address(this) before cancelllation: %s", _wnt.balanceOf(address(this))); \n\n    _roleStore.grantRole(address(222), Role.CONTROLLER); // to save a market's props\n    vm.prank(address(222));\n     _depositHandler.cancelDeposit(key1);\n    console.log("WNT balance of address(222) after cancelllation: %s", _wnt.balanceOf(address(222)));\n    console.log("WNT balance of address(this) after cancelllation: %s", _wnt.balanceOf(address(this))); \n}\n*/\n\nfunction testERC165() public{\n    bool yes = _wnt.supportsInterface(type(IWNT).interfaceId);\n    console2.log("wnt suppports deposit?");\n    console2.logBool(yes);\n    vm.expectRevert();\n    yes = IERC165(address(_sol)).supportsInterface(type(IWNT).interfaceId);\n    console2.logBool(yes);\n\n    if(ERC165Checker.supportsERC165(address(_wnt))){\n        console2.log("_wnt supports ERC165");\n    }\n    if(ERC165Checker.supportsERC165(address(_sol))){\n        console2.log("_sol supports ERC165");\n    }\n}\n\n    function justError() external {\n        // revert Unauthorized("abcdefg"); // 973d02cb\n        // revert("abcdefg");  // 0x08c379a, Error selector\n        // require(false, "abcdefg"); // 0x08ce79a, Error selector\n        assert(3 == 4); // Panic: 0x4e487b71\n    }\n\n     function testErrorMessage() public{\n\n        try this.justError(){}        \n        catch (bytes memory reasonBytes) {\n            (string memory msg, bool ok ) = ErrorUtils.getRevertMessage(reasonBytes);\n            console2.log("Error Message: "); console2.logString(msg);\n            console2.log("error?"); console2.logBool(ok);\n        }    \n    }\n\n    \n    function printAddresses() public{\n        console2.log("_orderVault:"); console2.logAddress(address(_orderVault));\n        console2.log("marketToken:"); console2.logAddress(address(_marketProps1.marketToken));\n    }   \n\n    function printPoolsAmounts() public{\n        console2.log("\n The summary of pool amounts: ");\n    \n        uint256 amount = MarketUtils.getPoolAmount(_dataStore, _marketProps1, _marketProps1.longToken);\n        console2.log("Market: _marketProps1, token: long/nwt, amount: %d", amount);\n        amount = MarketUtils.getPoolAmount(_dataStore, _marketProps1, _marketProps1.shortToken);\n        console2.log("Market: _marketProps1, token: short/USDC, amount: %d", amount);\n        \n        amount = MarketUtils.getPoolAmount(_dataStore, _marketPropsAB, _marketPropsAB.longToken);\n        console2.log("Market: _marketPropsAB, token: long/A, amount: %d", amount);\n        amount = MarketUtils.getPoolAmount(_dataStore, _marketPropsAB, _marketPropsAB.shortToken);\n        console2.log("Market: _marketPropsAB, token: short/B, amount: %d", amount);\n    \n        amount = MarketUtils.getPoolAmount(_dataStore, _marketPropsBC, _marketPropsBC.longToken);\n        console2.log("Market: _marketPropsBC, token: long/B, amount:%d", amount);\n        amount = MarketUtils.getPoolAmount(_dataStore, _marketPropsBC, _marketPropsBC.shortToken);\n        console2.log("Market: _marketPropsBC, token: short/C, amount: %d", amount);\n    \n        amount = MarketUtils.getPoolAmount(_dataStore, _marketPropsCwnt, _marketPropsCwnt.longToken);\n        console2.log("Market: _marketPropsCwnt, token: long/C, amount: %d", amount);\n        amount = MarketUtils.getPoolAmount(_dataStore, _marketPropsCwnt, _marketPropsCwnt.shortToken);\n        console2.log("Market: _marketPropsCwnt, token: short/wnt, amount: %d", amount);\n    \n\n        console2.log("\n");\n    }\n    \n}\n```\n